blob: 1a4de9271a88e9b941a98ad0cb7697f6c9a0e2ec [file] [log] [blame]
Junxiao Shi8c8d2182014-01-30 22:33:00 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi330136a2016-03-10 04:53:08 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shi82e7f582014-09-07 15:15:40 -070024 */
Junxiao Shi8c8d2182014-01-30 22:33:00 -070025
26#include "fw/forwarder.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070027#include "tests/daemon/face/dummy-face.hpp"
Junxiao Shif3c07812014-03-11 21:48:49 -070028#include "dummy-strategy.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070029
Junxiao Shid9ee45c2014-02-27 15:38:11 -070030#include "tests/test-common.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070031
32namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070033namespace tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070034
Junxiao Shi0355e9f2015-09-02 07:24:53 -070035BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shid41d6072016-06-19 23:35:27 +000036BOOST_FIXTURE_TEST_SUITE(TestForwarder, UnitTestTimeFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070037
Junxiao Shi8c8d2182014-01-30 22:33:00 -070038BOOST_AUTO_TEST_CASE(SimpleExchange)
39{
Junxiao Shic041ca32014-02-25 20:01:15 -070040 Forwarder forwarder;
41
Junxiao Shid41d6072016-06-19 23:35:27 +000042 Name nameA("ndn:/A");
43 Name nameAB("ndn:/A/B");
Junxiao Shi8c8d2182014-01-30 22:33:00 -070044 Name nameABC("ndn:/A/B/C");
Junxiao Shif3c07812014-03-11 21:48:49 -070045 shared_ptr<Interest> interestAB = makeInterest(nameAB);
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070046 interestAB->setInterestLifetime(time::seconds(4));
Junxiao Shif3c07812014-03-11 21:48:49 -070047 shared_ptr<Data> dataABC = makeData(nameABC);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070048
Junxiao Shicde37ad2015-12-24 01:02:05 -070049 auto face1 = make_shared<DummyFace>();
50 auto face2 = make_shared<DummyFace>();
Junxiao Shi8c8d2182014-01-30 22:33:00 -070051 forwarder.addFace(face1);
52 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -070053
Junxiao Shi8c8d2182014-01-30 22:33:00 -070054 Fib& fib = forwarder.getFib();
Junxiao Shi6e694322014-04-03 10:27:13 -070055 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
Junxiao Shi8c8d2182014-01-30 22:33:00 -070056 fibEntry->addNextHop(face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070057
Junxiao Shida93f1f2015-11-11 06:13:16 -070058 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
59 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000060 face1->receiveInterest(*interestAB);
61 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070062 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
63 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), nameAB);
64 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
65 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070066 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
67 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -070068
Junxiao Shida93f1f2015-11-11 06:13:16 -070069 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
70 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Junxiao Shid41d6072016-06-19 23:35:27 +000071 face2->receiveData(*dataABC);
72 this->advanceClocks(time::milliseconds(100), time::seconds(1));
Junxiao Shicde37ad2015-12-24 01:02:05 -070073 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
74 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), nameABC);
75 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
76 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070077 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
78 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070079}
80
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070081BOOST_AUTO_TEST_CASE(CsMatched)
82{
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070083 Forwarder forwarder;
84
Junxiao Shicde37ad2015-12-24 01:02:05 -070085 auto face1 = make_shared<DummyFace>();
86 auto face2 = make_shared<DummyFace>();
87 auto face3 = make_shared<DummyFace>();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070088 forwarder.addFace(face1);
89 forwarder.addFace(face2);
90 forwarder.addFace(face3);
91
92 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
93 interestA->setInterestLifetime(time::seconds(4));
94 shared_ptr<Data> dataA = makeData("ndn:/A");
Junxiao Shi0de23a22015-12-03 20:07:02 +000095 dataA->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -070096
97 Fib& fib = forwarder.getFib();
98 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
99 fibEntry->addNextHop(face2, 0);
100
101 Pit& pit = forwarder.getPit();
102 BOOST_CHECK_EQUAL(pit.size(), 0);
103
104 Cs& cs = forwarder.getCs();
Minsheng Zhangffe8bbb2016-03-10 13:40:37 -0700105 cs.insert(*dataA);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700106
107 face1->receiveInterest(*interestA);
Junxiao Shid41d6072016-06-19 23:35:27 +0000108 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700109 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700110 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700111
Junxiao Shicde37ad2015-12-24 01:02:05 -0700112 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700113 // IncomingFaceId field should be reset to represent CS
Junxiao Shicde37ad2015-12-24 01:02:05 -0700114 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
115 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700116
Junxiao Shid41d6072016-06-19 23:35:27 +0000117 this->advanceClocks(time::milliseconds(100), time::milliseconds(500));
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700118 // PIT entry should not be left behind
119 BOOST_CHECK_EQUAL(pit.size(), 0);
120}
121
Junxiao Shi891f47b2016-06-20 00:02:11 +0000122BOOST_AUTO_TEST_CASE(OutgoingInterest)
123{
124 Forwarder forwarder;
125 auto face1 = make_shared<DummyFace>();
126 auto face2 = make_shared<DummyFace>();
127 auto face3 = make_shared<DummyFace>();
128 forwarder.addFace(face1);
129 forwarder.addFace(face2);
130 forwarder.addFace(face3);
131
132 Pit& pit = forwarder.getPit();
133 auto interestA1 = makeInterest("ndn:/A");
134 interestA1->setNonce(8378);
135 shared_ptr<pit::Entry> pitA = pit.insert(*interestA1).first;
136 pit::InRecordCollection::iterator inA1 = pitA->insertOrUpdateInRecord(face1, *interestA1);
137
138 // there is only one downstream, interestA1 is used
139 forwarder.onOutgoingInterest(pitA, *face3, false);
140 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 1);
141 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 8378);
142
143 // new Nonce is requested
144 forwarder.onOutgoingInterest(pitA, *face3, true);
145 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 2);
146 BOOST_CHECK_NE(face3->sentInterests.back().getNonce(), 8378);
147 // Nonce on in-record Interest shouldn't be touched
148 BOOST_CHECK_EQUAL(inA1->getInterest().getNonce(), 8378);
149
150 // outgoing face is face1, interestA1 is still used because there's no other choice
151 forwarder.onOutgoingInterest(pitA, *face1, false);
152 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 1);
153 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 8378);
154
155 this->advanceClocks(time::seconds(2));
156 auto interestA2 = makeInterest("ndn:/A");
157 interestA2->setNonce(9102);
158 pitA->insertOrUpdateInRecord(face2, *interestA2);
159
160 // there are two downstreams, prefer newer interestA2
161 forwarder.onOutgoingInterest(pitA, *face3, false);
162 BOOST_REQUIRE_EQUAL(face3->sentInterests.size(), 3);
163 BOOST_CHECK_EQUAL(face3->sentInterests.back().getNonce(), 9102);
164
165 // outgoing face is face2, prefer interestA1 from face1 despite it's older
166 forwarder.onOutgoingInterest(pitA, *face2, false);
167 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
168 BOOST_CHECK_EQUAL(face2->sentInterests.back().getNonce(), 8378);
169
170 // outgoing face is face1, prefer interestA2
171 forwarder.onOutgoingInterest(pitA, *face1, false);
172 BOOST_REQUIRE_EQUAL(face1->sentInterests.size(), 2);
173 BOOST_CHECK_EQUAL(face1->sentInterests.back().getNonce(), 9102);
174}
175
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700176class ScopeLocalhostIncomingTestForwarder : public Forwarder
Junxiao Shi88884492014-02-15 15:57:43 -0700177{
178public:
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700179 ScopeLocalhostIncomingTestForwarder()
Junxiao Shi88884492014-02-15 15:57:43 -0700180 {
181 }
182
183 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200184 onDataUnsolicited(Face& inFace, const Data& data) override
Junxiao Shi88884492014-02-15 15:57:43 -0700185 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700186 ++onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700187 }
188
189protected:
190 virtual void
Davide Pesaventob84bd3a2016-04-22 02:21:45 +0200191 dispatchToStrategy(shared_ptr<pit::Entry> pitEntry, function<void(fw::Strategy*)> f) override
Junxiao Shi88884492014-02-15 15:57:43 -0700192 {
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700193 ++dispatchToStrategy_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700194 }
195
196public:
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700197 int dispatchToStrategy_count;
198 int onDataUnsolicited_count;
Junxiao Shi88884492014-02-15 15:57:43 -0700199};
200
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700201BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700202{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700203 ScopeLocalhostIncomingTestForwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700204 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
205 auto face2 = make_shared<DummyFace>();
Junxiao Shi88884492014-02-15 15:57:43 -0700206 forwarder.addFace(face1);
207 forwarder.addFace(face2);
Junxiao Shic041ca32014-02-25 20:01:15 -0700208
Junxiao Shi88884492014-02-15 15:57:43 -0700209 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700210 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700211 shared_ptr<Interest> i1 = makeInterest("/localhost/A1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800212 forwarder.onIncomingInterest(*face1, *i1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700213 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700214
Junxiao Shi88884492014-02-15 15:57:43 -0700215 // non-local face, /localhost: violate
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700216 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700217 shared_ptr<Interest> i2 = makeInterest("/localhost/A2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800218 forwarder.onIncomingInterest(*face2, *i2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700219 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700220
Junxiao Shi88884492014-02-15 15:57:43 -0700221 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700222 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700223 shared_ptr<Interest> i3 = makeInterest("/A3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800224 forwarder.onIncomingInterest(*face1, *i3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700225 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700226
Junxiao Shi88884492014-02-15 15:57:43 -0700227 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700228 forwarder.dispatchToStrategy_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700229 shared_ptr<Interest> i4 = makeInterest("/A4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800230 forwarder.onIncomingInterest(*face2, *i4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700231 BOOST_CHECK_EQUAL(forwarder.dispatchToStrategy_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700232
Junxiao Shi88884492014-02-15 15:57:43 -0700233 // local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700234 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700235 shared_ptr<Data> d1 = makeData("/localhost/B1");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800236 forwarder.onIncomingData(*face1, *d1);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700237 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700238
239 // non-local face, /localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700240 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700241 shared_ptr<Data> d2 = makeData("/localhost/B2");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800242 forwarder.onIncomingData(*face2, *d2);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700243 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700244
Junxiao Shi88884492014-02-15 15:57:43 -0700245 // local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700246 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700247 shared_ptr<Data> d3 = makeData("/B3");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800248 forwarder.onIncomingData(*face1, *d3);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700249 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700250
251 // non-local face, non-/localhost: OK
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700252 forwarder.onDataUnsolicited_count = 0;
Junxiao Shif3c07812014-03-11 21:48:49 -0700253 shared_ptr<Data> d4 = makeData("/B4");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800254 forwarder.onIncomingData(*face2, *d4);
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700255 BOOST_CHECK_EQUAL(forwarder.onDataUnsolicited_count, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700256}
257
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700258BOOST_AUTO_TEST_CASE(ScopeLocalhostOutgoing)
259{
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700260 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700261 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
262 auto face2 = make_shared<DummyFace>();
263 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700264 forwarder.addFace(face1);
265 forwarder.addFace(face2);
266 forwarder.addFace(face3);
267 Pit& pit = forwarder.getPit();
268
269 // local face, /localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700270 shared_ptr<Interest> interestA1 = makeInterest("/localhost/A1");
271 shared_ptr<pit::Entry> pitA1 = pit.insert(*interestA1).first;
272 pitA1->insertOrUpdateInRecord(face3, *interestA1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700273 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700274 forwarder.onOutgoingInterest(pitA1, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700275 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700276
277 // non-local face, /localhost: violate
Junxiao Shif3c07812014-03-11 21:48:49 -0700278 shared_ptr<Interest> interestA2 = makeInterest("/localhost/A2");
279 shared_ptr<pit::Entry> pitA2 = pit.insert(*interestA2).first;
280 pitA2->insertOrUpdateInRecord(face3, *interestA2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700281 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700282 forwarder.onOutgoingInterest(pitA2, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700283 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700284
285 // local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700286 shared_ptr<Interest> interestA3 = makeInterest("/A3");
287 shared_ptr<pit::Entry> pitA3 = pit.insert(*interestA3).first;
288 pitA3->insertOrUpdateInRecord(face3, *interestA3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700289 face1->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700290 forwarder.onOutgoingInterest(pitA3, *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700291 BOOST_CHECK_EQUAL(face1->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700292
293 // non-local face, non-/localhost: OK
Junxiao Shif3c07812014-03-11 21:48:49 -0700294 shared_ptr<Interest> interestA4 = makeInterest("/A4");
295 shared_ptr<pit::Entry> pitA4 = pit.insert(*interestA4).first;
296 pitA4->insertOrUpdateInRecord(face3, *interestA4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700297 face2->sentInterests.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700298 forwarder.onOutgoingInterest(pitA4, *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700299 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700300
301 // local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700302 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700303 forwarder.onOutgoingData(Data("/localhost/B1"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700304 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700305
306 // non-local face, /localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700307 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700308 forwarder.onOutgoingData(Data("/localhost/B2"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700309 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700310
311 // local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700312 face1->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700313 forwarder.onOutgoingData(Data("/B3"), *face1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700314 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700315
316 // non-local face, non-/localhost: OK
Junxiao Shicde37ad2015-12-24 01:02:05 -0700317 face2->sentData.clear();
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700318 forwarder.onOutgoingData(Data("/B4"), *face2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700319 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
Junxiao Shi9b27bd22014-02-26 20:29:58 -0700320}
321
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700322BOOST_AUTO_TEST_CASE(ScopeLocalhopOutgoing)
323{
324 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700325 auto face1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
326 auto face2 = make_shared<DummyFace>();
327 auto face3 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
328 auto face4 = make_shared<DummyFace>();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700329 forwarder.addFace(face1);
330 forwarder.addFace(face2);
331 forwarder.addFace(face3);
332 forwarder.addFace(face4);
333 Pit& pit = forwarder.getPit();
334
335 // from local face, to local face: OK
336 shared_ptr<Interest> interest1 = makeInterest("/localhop/1");
337 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
338 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700339 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700340 forwarder.onOutgoingInterest(pit1, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700341 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700342
343 // from non-local face, to local face: OK
344 shared_ptr<Interest> interest2 = makeInterest("/localhop/2");
345 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
346 pit2->insertOrUpdateInRecord(face2, *interest2);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700347 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700348 forwarder.onOutgoingInterest(pit2, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700349 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700350
351 // from local face, to non-local face: OK
352 shared_ptr<Interest> interest3 = makeInterest("/localhop/3");
353 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
354 pit3->insertOrUpdateInRecord(face1, *interest3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700355 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700356 forwarder.onOutgoingInterest(pit3, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700357 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700358
359 // from non-local face, to non-local face: violate
360 shared_ptr<Interest> interest4 = makeInterest("/localhop/4");
361 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
362 pit4->insertOrUpdateInRecord(face2, *interest4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700363 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700364 forwarder.onOutgoingInterest(pit4, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700365 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 0);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700366
367 // from local face and non-local face, to local face: OK
368 shared_ptr<Interest> interest5 = makeInterest("/localhop/5");
369 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
370 pit5->insertOrUpdateInRecord(face1, *interest5);
371 pit5->insertOrUpdateInRecord(face2, *interest5);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700372 face3->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700373 forwarder.onOutgoingInterest(pit5, *face3);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700374 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700375
376 // from local face and non-local face, to non-local face: OK
377 shared_ptr<Interest> interest6 = makeInterest("/localhop/6");
378 shared_ptr<pit::Entry> pit6 = pit.insert(*interest6).first;
379 pit6->insertOrUpdateInRecord(face1, *interest6);
380 pit6->insertOrUpdateInRecord(face2, *interest6);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700381 face4->sentInterests.clear();
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700382 forwarder.onOutgoingInterest(pit6, *face4);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700383 BOOST_CHECK_EQUAL(face4->sentInterests.size(), 1);
Junxiao Shi11bd9c22014-03-13 20:44:13 -0700384}
385
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700386BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700387{
Junxiao Shif3c07812014-03-11 21:48:49 -0700388 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700389 auto face1 = make_shared<DummyFace>();
390 auto face2 = make_shared<DummyFace>();
Junxiao Shif3c07812014-03-11 21:48:49 -0700391 forwarder.addFace(face1);
392 forwarder.addFace(face2);
393
394 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
395 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700396 ref(forwarder), "ndn:/strategyP");
Junxiao Shif3c07812014-03-11 21:48:49 -0700397 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700398 ref(forwarder), "ndn:/strategyQ");
Junxiao Shif3c07812014-03-11 21:48:49 -0700399 strategyChoice.install(strategyP);
400 strategyChoice.install(strategyQ);
401 strategyChoice.insert("ndn:/" , strategyP->getName());
402 strategyChoice.insert("ndn:/B", strategyQ->getName());
403
404 shared_ptr<Interest> interest1 = makeInterest("ndn:/A/1");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700405 strategyP->afterReceiveInterest_count = 0;
406 strategyP->interestOutFace = face2;
407 forwarder.startProcessInterest(*face1, *interest1);
408 BOOST_CHECK_EQUAL(strategyP->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700409
410 shared_ptr<Interest> interest2 = makeInterest("ndn:/B/2");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700411 strategyQ->afterReceiveInterest_count = 0;
412 strategyQ->interestOutFace = face2;
413 forwarder.startProcessInterest(*face1, *interest2);
414 BOOST_CHECK_EQUAL(strategyQ->afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700415
Junxiao Shid41d6072016-06-19 23:35:27 +0000416 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shif3c07812014-03-11 21:48:49 -0700417
418 shared_ptr<Data> data1 = makeData("ndn:/A/1/a");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700419 strategyP->beforeSatisfyInterest_count = 0;
420 forwarder.startProcessData(*face2, *data1);
421 BOOST_CHECK_EQUAL(strategyP->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700422
423 shared_ptr<Data> data2 = makeData("ndn:/B/2/b");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700424 strategyQ->beforeSatisfyInterest_count = 0;
425 forwarder.startProcessData(*face2, *data2);
426 BOOST_CHECK_EQUAL(strategyQ->beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700427
428 shared_ptr<Interest> interest3 = makeInterest("ndn:/A/3");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700429 interest3->setInterestLifetime(time::milliseconds(30));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700430 forwarder.startProcessInterest(*face1, *interest3);
Junxiao Shif3c07812014-03-11 21:48:49 -0700431 shared_ptr<Interest> interest4 = makeInterest("ndn:/B/4");
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700432 interest4->setInterestLifetime(time::milliseconds(5000));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700433 forwarder.startProcessInterest(*face1, *interest4);
Junxiao Shif3c07812014-03-11 21:48:49 -0700434
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700435 strategyP->beforeExpirePendingInterest_count = 0;
436 strategyQ->beforeExpirePendingInterest_count = 0;
Junxiao Shid41d6072016-06-19 23:35:27 +0000437 this->advanceClocks(time::milliseconds(10), time::milliseconds(100));
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700438 BOOST_CHECK_EQUAL(strategyP->beforeExpirePendingInterest_count, 1);
439 BOOST_CHECK_EQUAL(strategyQ->beforeExpirePendingInterest_count, 0);
Junxiao Shif3c07812014-03-11 21:48:49 -0700440}
441
Junxiao Shida006f52014-05-16 11:18:00 -0700442BOOST_AUTO_TEST_CASE(IncomingData)
443{
Junxiao Shida006f52014-05-16 11:18:00 -0700444 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700445 auto face1 = make_shared<DummyFace>();
446 auto face2 = make_shared<DummyFace>();
447 auto face3 = make_shared<DummyFace>();
448 auto face4 = make_shared<DummyFace>();
Junxiao Shida006f52014-05-16 11:18:00 -0700449 forwarder.addFace(face1);
450 forwarder.addFace(face2);
Junxiao Shi223271b2014-07-03 22:06:13 -0700451 forwarder.addFace(face3);
452 forwarder.addFace(face4);
Junxiao Shida006f52014-05-16 11:18:00 -0700453
454 Pit& pit = forwarder.getPit();
455 shared_ptr<Interest> interest0 = makeInterest("ndn:/");
456 shared_ptr<pit::Entry> pit0 = pit.insert(*interest0).first;
457 pit0->insertOrUpdateInRecord(face1, *interest0);
458 shared_ptr<Interest> interestA = makeInterest("ndn:/A");
459 shared_ptr<pit::Entry> pitA = pit.insert(*interestA).first;
460 pitA->insertOrUpdateInRecord(face1, *interestA);
461 pitA->insertOrUpdateInRecord(face2, *interestA);
462 shared_ptr<Interest> interestC = makeInterest("ndn:/A/B/C");
463 shared_ptr<pit::Entry> pitC = pit.insert(*interestC).first;
464 pitC->insertOrUpdateInRecord(face3, *interestC);
465 pitC->insertOrUpdateInRecord(face4, *interestC);
466
467 shared_ptr<Data> dataD = makeData("ndn:/A/B/C/D");
468 forwarder.onIncomingData(*face3, *dataD);
Junxiao Shid41d6072016-06-19 23:35:27 +0000469 this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
Junxiao Shida006f52014-05-16 11:18:00 -0700470
Junxiao Shicde37ad2015-12-24 01:02:05 -0700471 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
472 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
473 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
474 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Junxiao Shida006f52014-05-16 11:18:00 -0700475}
476
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700477BOOST_AUTO_TEST_CASE(IncomingNack)
478{
479 Forwarder forwarder;
480 auto face1 = make_shared<DummyFace>();
481 auto face2 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700482 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
483 ndn::nfd::FACE_SCOPE_NON_LOCAL,
484 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
485 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700486 forwarder.addFace(face1);
487 forwarder.addFace(face2);
488 forwarder.addFace(face3);
489
490 StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
491 shared_ptr<DummyStrategy> strategyP = make_shared<DummyStrategy>(
492 ref(forwarder), "ndn:/strategyP");
493 shared_ptr<DummyStrategy> strategyQ = make_shared<DummyStrategy>(
494 ref(forwarder), "ndn:/strategyQ");
495 strategyChoice.install(strategyP);
496 strategyChoice.install(strategyQ);
497 strategyChoice.insert("ndn:/" , strategyP->getName());
498 strategyChoice.insert("ndn:/B", strategyQ->getName());
499
500 Pit& pit = forwarder.getPit();
501
502 // dispatch to the correct strategy
503 shared_ptr<Interest> interest1 = makeInterest("/A/AYJqayrzF", 562);
504 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
505 pit1->insertOrUpdateOutRecord(face1, *interest1);
506 shared_ptr<Interest> interest2 = makeInterest("/B/EVyP73ru", 221);
507 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
508 pit2->insertOrUpdateOutRecord(face1, *interest2);
509
510 lp::Nack nack1 = makeNack("/A/AYJqayrzF", 562, lp::NackReason::CONGESTION);
511 strategyP->afterReceiveNack_count = 0;
512 strategyQ->afterReceiveNack_count = 0;
513 forwarder.onIncomingNack(*face1, nack1);
514 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 1);
515 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
516
517 lp::Nack nack2 = makeNack("/B/EVyP73ru", 221, lp::NackReason::CONGESTION);
518 strategyP->afterReceiveNack_count = 0;
519 strategyQ->afterReceiveNack_count = 0;
520 forwarder.onIncomingNack(*face1, nack2);
521 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
522 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 1);
523
524 // record Nack on PIT out-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700525 pit::OutRecordCollection::iterator outRecord1 = pit1->getOutRecord(*face1);
526 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700527 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
528 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
529
530 // drop if no PIT entry
531 lp::Nack nack3 = makeNack("/yEcw5HhdM", 243, lp::NackReason::CONGESTION);
532 strategyP->afterReceiveNack_count = 0;
533 strategyQ->afterReceiveNack_count = 0;
534 forwarder.onIncomingNack(*face1, nack3);
535 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
536 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
537
538 // drop if no out-record
539 shared_ptr<Interest> interest4 = makeInterest("/Etab4KpY", 157);
540 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
541 pit4->insertOrUpdateOutRecord(face1, *interest4);
542
543 lp::Nack nack4a = makeNack("/Etab4KpY", 157, lp::NackReason::CONGESTION);
544 strategyP->afterReceiveNack_count = 0;
545 strategyQ->afterReceiveNack_count = 0;
546 forwarder.onIncomingNack(*face2, nack4a);
547 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
548 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
549
550 // drop if Nonce does not match out-record
551 lp::Nack nack4b = makeNack("/Etab4KpY", 294, lp::NackReason::CONGESTION);
552 strategyP->afterReceiveNack_count = 0;
553 strategyQ->afterReceiveNack_count = 0;
554 forwarder.onIncomingNack(*face1, nack4b);
555 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
556 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
557
558 // drop if inFace is multi-access
559 pit4->insertOrUpdateOutRecord(face3, *interest4);
560 strategyP->afterReceiveNack_count = 0;
561 strategyQ->afterReceiveNack_count = 0;
562 forwarder.onIncomingNack(*face3, nack4a);
563 BOOST_CHECK_EQUAL(strategyP->afterReceiveNack_count, 0);
564 BOOST_CHECK_EQUAL(strategyQ->afterReceiveNack_count, 0);
565}
566
567BOOST_AUTO_TEST_CASE(OutgoingNack)
568{
569 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700570 auto face1 = make_shared<DummyFace>();
571 auto face2 = make_shared<DummyFace>();
572 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
573 ndn::nfd::FACE_SCOPE_NON_LOCAL,
574 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
575 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
576 forwarder.addFace(face1);
577 forwarder.addFace(face2);
578 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700579
580 Pit& pit = forwarder.getPit();
581
582 lp::NackHeader nackHeader;
583 nackHeader.setReason(lp::NackReason::CONGESTION);
584
585 // don't send Nack if there's no in-record
586 shared_ptr<Interest> interest1 = makeInterest("/fM5IVEtC", 719);
587 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700588 pit1->insertOrUpdateInRecord(face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700589
590 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700591 forwarder.onOutgoingNack(pit1, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700592 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
593
594 // send Nack with correct Nonce
595 shared_ptr<Interest> interest2a = makeInterest("/Vi8tRm9MG3", 152);
596 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2a).first;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700597 pit2->insertOrUpdateInRecord(face1, *interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700598 shared_ptr<Interest> interest2b = makeInterest("/Vi8tRm9MG3", 808);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700599 pit2->insertOrUpdateInRecord(face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700600
601 face1->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700602 forwarder.onOutgoingNack(pit2, *face1, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700603 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
604 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
605 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
606
607 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700608 pit::InRecordCollection::iterator inRecord2a = pit2->getInRecord(*face1);
609 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700610
611 // send Nack with correct Nonce
612 face2->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700613 forwarder.onOutgoingNack(pit2, *face2, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700614 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
615 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
616 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
617
618 // erase in-record
Junxiao Shi4846f372016-04-05 13:39:30 -0700619 pit::InRecordCollection::iterator inRecord2b = pit2->getInRecord(*face1);
620 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700621
622 // don't send Nack to multi-access face
623 shared_ptr<Interest> interest2c = makeInterest("/Vi8tRm9MG3", 228);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700624 pit2->insertOrUpdateInRecord(face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700625
626 face3->sentNacks.clear();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700627 forwarder.onOutgoingNack(pit1, *face3, nackHeader);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700628 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
629}
630
631BOOST_AUTO_TEST_CASE(InterestLoopNack)
632{
633 Forwarder forwarder;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700634 auto face1 = make_shared<DummyFace>();
635 auto face2 = make_shared<DummyFace>();
636 auto face3 = make_shared<DummyFace>("dummy://", "dummy://",
637 ndn::nfd::FACE_SCOPE_NON_LOCAL,
638 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
639 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700640 auto face4 = make_shared<DummyFace>();
Junxiao Shicde37ad2015-12-24 01:02:05 -0700641 forwarder.addFace(face1);
642 forwarder.addFace(face2);
643 forwarder.addFace(face3);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700644 forwarder.addFace(face4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700645
646 Fib& fib = forwarder.getFib();
647 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("/zT4XwK0Hnx")).first;
648 fibEntry->addNextHop(face4, 0);
649
650 // receive Interest on face1
651 face1->sentNacks.clear();
652 shared_ptr<Interest> interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
653 face1->receiveInterest(*interest1a);
654 BOOST_CHECK(face1->sentNacks.empty());
655
656 // receive Interest with duplicate Nonce on face1
657 face1->sentNacks.clear();
658 shared_ptr<Interest> interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
659 face1->receiveInterest(*interest1b);
660 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
661 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest(), *interest1b);
662 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
663
664 // receive Interest with duplicate Nonce on face2
665 face2->sentNacks.clear();
666 shared_ptr<Interest> interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
667 face2->receiveInterest(*interest2a);
668 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
669 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest(), *interest2a);
670 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
671
672 // receive Interest with new Nonce on face2
673 face2->sentNacks.clear();
674 shared_ptr<Interest> interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 944);
675 face2->receiveInterest(*interest2b);
676 BOOST_CHECK(face2->sentNacks.empty());
677
678 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
679 face3->sentNacks.clear();
680 shared_ptr<Interest> interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", 732);
681 face3->receiveInterest(*interest3a);
682 BOOST_CHECK(face3->sentNacks.empty());
683}
684
Junxiao Shi455581d2014-11-17 18:38:40 -0700685BOOST_FIXTURE_TEST_CASE(InterestLoopWithShortLifetime, UnitTestTimeFixture) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700686{
Junxiao Shia110f262014-10-12 12:35:20 -0700687 Forwarder forwarder;
Junxiao Shi455581d2014-11-17 18:38:40 -0700688 auto face1 = make_shared<DummyFace>();
689 auto face2 = make_shared<DummyFace>();
Junxiao Shia110f262014-10-12 12:35:20 -0700690 forwarder.addFace(face1);
691 forwarder.addFace(face2);
692
693 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700694 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
695 if (pktType == tlv::Interest) {
696 auto interest = make_shared<Interest>(face2->sentInterests.back());
697 scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
698 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700699 });
Junxiao Shia110f262014-10-12 12:35:20 -0700700
701 Fib& fib = forwarder.getFib();
702 shared_ptr<fib::Entry> fibEntry = fib.insert(Name("ndn:/A")).first;
703 fibEntry->addNextHop(face2, 0);
704
Junxiao Shi455581d2014-11-17 18:38:40 -0700705 // receive an Interest
Junxiao Shia110f262014-10-12 12:35:20 -0700706 shared_ptr<Interest> interest = makeInterest("ndn:/A/1");
707 interest->setNonce(82101183);
708 interest->setInterestLifetime(time::milliseconds(50));
709 face1->receiveInterest(*interest);
710
Junxiao Shi455581d2014-11-17 18:38:40 -0700711 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
712 BOOST_ASSERT(time::milliseconds(25) * 40 < forwarder.getDeadNonceList().getLifetime());
713 this->advanceClocks(time::milliseconds(25), 40);
Junxiao Shia110f262014-10-12 12:35:20 -0700714
Junxiao Shicde37ad2015-12-24 01:02:05 -0700715 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700716
717 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
718 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
719 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
720 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
721 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700722}
723
Junxiao Shid41d6072016-06-19 23:35:27 +0000724BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700725{
726 Forwarder forwarder;
727 shared_ptr<Face> face1 = make_shared<DummyFace>();
728 forwarder.addFace(face1);
729
730 shared_ptr<Interest> interest = makeInterest("ndn:/hcLSAsQ9A");
731 interest->setNonce(61883075);
732 interest->setInterestLifetime(time::seconds(2));
733
734 DeadNonceList& dnl = forwarder.getDeadNonceList();
735 dnl.add(interest->getName(), interest->getNonce());
736 Pit& pit = forwarder.getPit();
737 BOOST_REQUIRE_EQUAL(pit.size(), 0);
738
739 forwarder.startProcessInterest(*face1, *interest);
740 this->advanceClocks(time::milliseconds(100), time::seconds(20));
741 BOOST_CHECK_EQUAL(pit.size(), 0);
742}
743
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700744BOOST_AUTO_TEST_CASE(LinkDelegation)
745{
746 Forwarder forwarder;
747 shared_ptr<Face> face1 = make_shared<DummyFace>();
748 shared_ptr<Face> face2 = make_shared<DummyFace>();
749 forwarder.addFace(face1);
750 forwarder.addFace(face2);
751
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700752 Fib& fib = forwarder.getFib();
753 Pit& pit = forwarder.getPit();
754 NetworkRegionTable& nrt = forwarder.getNetworkRegionTable();
755
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700756 shared_ptr<Link> link = makeLink("/net/ndnsim", {{10, "/telia/terabits"}, {20, "/ucla/cs"}});
757
758 // consumer region
759 nrt.clear();
760 nrt.insert("/arizona/cs/avenir");
761 shared_ptr<fib::Entry> fibRoot = fib.insert("/").first;
762 fibRoot->addNextHop(face2, 10);
763
764 auto interest1 = makeInterest("/net/ndnsim/www/1.html");
765 interest1->setLink(link->wireEncode());
766 shared_ptr<pit::Entry> pit1 = pit.insert(*interest1).first;
767 pit1->insertOrUpdateInRecord(face1, *interest1);
768
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000769 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700770 BOOST_CHECK_EQUAL(interest1->hasSelectedDelegation(), false);
771
772 fibRoot->removeNextHop(face2);
773
774 // first default-free router, both delegations are available
775 nrt.clear();
776 nrt.insert("/arizona/cs/hobo");
777 shared_ptr<fib::Entry> fibTelia = fib.insert("/telia").first;
778 fibTelia->addNextHop(face2, 10);
779 shared_ptr<fib::Entry> fibUcla = fib.insert("/ucla").first;
780 fibUcla->addNextHop(face2, 10);
781
782 auto interest2 = makeInterest("/net/ndnsim/www/2.html");
783 interest2->setLink(link->wireEncode());
784 shared_ptr<pit::Entry> pit2 = pit.insert(*interest2).first;
785 pit2->insertOrUpdateInRecord(face1, *interest2);
786
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000787 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit2).getPrefix(), "/telia");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700788 BOOST_REQUIRE_EQUAL(interest2->hasSelectedDelegation(), true);
789 BOOST_CHECK_EQUAL(interest2->getSelectedDelegation(), "/telia/terabits");
790
791 fib.erase(*fibTelia);
792 fib.erase(*fibUcla);
793
794 // first default-free router, only second delegation is available
795 nrt.clear();
796 nrt.insert("/arizona/cs/hobo");
797 fibUcla = fib.insert("/ucla").first;
798 fibUcla->addNextHop(face2, 10);
799
800 auto interest3 = makeInterest("/net/ndnsim/www/3.html");
801 interest3->setLink(link->wireEncode());
802 shared_ptr<pit::Entry> pit3 = pit.insert(*interest3).first;
803 pit3->insertOrUpdateInRecord(face1, *interest3);
804
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000805 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit3).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700806 BOOST_REQUIRE_EQUAL(interest3->hasSelectedDelegation(), true);
807 BOOST_CHECK_EQUAL(interest3->getSelectedDelegation(), "/ucla/cs");
808
809 fib.erase(*fibUcla);
810
811 // default-free router, chosen SelectedDelegation
812 nrt.clear();
813 nrt.insert("/ucsd/caida/click");
814 fibTelia = fib.insert("/telia").first;
815 fibTelia->addNextHop(face2, 10);
816 fibUcla = fib.insert("/ucla").first;
817 fibUcla->addNextHop(face2, 10);
818
819 auto interest4 = makeInterest("/net/ndnsim/www/4.html");
820 interest4->setLink(link->wireEncode());
821 interest4->setSelectedDelegation("/ucla/cs");
822 shared_ptr<pit::Entry> pit4 = pit.insert(*interest4).first;
823 pit4->insertOrUpdateInRecord(face1, *interest4);
824
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000825 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit4).getPrefix(), "/ucla");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700826 BOOST_REQUIRE_EQUAL(interest4->hasSelectedDelegation(), true);
827 BOOST_CHECK_EQUAL(interest4->getSelectedDelegation(), "/ucla/cs");
828
829 fib.erase(*fibTelia);
830 fib.erase(*fibUcla);
831
832 // producer region
833 nrt.clear();
834 nrt.insert("/ucla/cs/spurs");
835 fibRoot->addNextHop(face2, 10);
836 fibUcla = fib.insert("/ucla").first;
837 fibUcla->addNextHop(face2, 10);
838 shared_ptr<fib::Entry> fibNdnsim = fib.insert("/net/ndnsim").first;
839 fibNdnsim->addNextHop(face2, 10);
840
841 auto interest5 = makeInterest("/net/ndnsim/www/5.html");
842 interest5->setLink(link->wireEncode());
843 interest5->setSelectedDelegation("/ucla/cs");
844 shared_ptr<pit::Entry> pit5 = pit.insert(*interest5).first;
845 pit5->insertOrUpdateInRecord(face1, *interest5);
846
Junxiao Shi05cc50a2016-07-11 22:38:21 +0000847 BOOST_CHECK_EQUAL(forwarder.lookupFib(*pit1).getPrefix(), "/net/ndnsim");
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700848 BOOST_REQUIRE_EQUAL(interest5->hasSelectedDelegation(), true);
849 BOOST_CHECK_EQUAL(interest5->getSelectedDelegation(), "/ucla/cs");
850
851 fibRoot->removeNextHop(face2);
852 fib.erase(*fibUcla);
853 fib.erase(*fibNdnsim);
854}
855
856
857class MalformedPacketFixture : public UnitTestTimeFixture
858{
859protected:
860 MalformedPacketFixture()
861 : face1(make_shared<DummyFace>())
862 , face2(make_shared<DummyFace>())
863 {
864 forwarder.addFace(face1);
865 forwarder.addFace(face2);
866 }
867
868 void
869 processInterest(shared_ptr<Interest> badInterest)
870 {
871 forwarder.startProcessInterest(*face1, *badInterest);
872 this->continueProcessPacket();
873 }
874
875 // processData
876
877 // processNack
878
879private:
880 void
881 continueProcessPacket()
882 {
883 this->advanceClocks(time::milliseconds(10), time::seconds(6));
884 }
885
886protected:
887 Forwarder forwarder;
888 shared_ptr<DummyFace> face1; // face of incoming bad packet
889 shared_ptr<DummyFace> face2; // another face for setting up states
890};
891
892BOOST_FIXTURE_TEST_SUITE(MalformedPacket, MalformedPacketFixture)
893
894BOOST_AUTO_TEST_CASE(BadLink)
895{
896 shared_ptr<Interest> goodInterest = makeInterest("ndn:/");
897 Block wire = goodInterest->wireEncode();
898 wire.push_back(ndn::encoding::makeEmptyBlock(tlv::Data)); // bad Link
899 wire.encode();
900
901 auto badInterest = make_shared<Interest>();
902 BOOST_REQUIRE_NO_THROW(badInterest->wireDecode(wire));
903 BOOST_REQUIRE(badInterest->hasLink());
904 BOOST_REQUIRE_THROW(badInterest->getLink(), tlv::Error);
905
906 BOOST_CHECK_NO_THROW(this->processInterest(badInterest));
907}
908
909BOOST_AUTO_TEST_SUITE_END() // MalformedPacket
910
911BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700912BOOST_AUTO_TEST_SUITE_END()
913
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700914} // namespace tests
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700915} // namespace nfd