blob: 4ade6741dbf80c2b539e5fc6c2347feb0b3fcb31 [file] [log] [blame]
Vince Lehman942eb7b2014-10-02 10:09:27 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014 University of Memphis,
4 * Regents of the University of California
5 *
6 * This file is part of NLSR (Named-data Link State Routing).
7 * See AUTHORS.md for complete list of NLSR authors and contributors.
8 *
9 * NLSR is free software: you can redistribute it and/or modify it under the terms
10 * of the GNU General Public License as published by the Free Software Foundation,
11 * either version 3 of the License, or (at your option) any later version.
12 *
13 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
19 *
20 **/
21
22#include "test-common.hpp"
23#include "control-commands.hpp"
24#include "dummy-face.hpp"
25
26#include "route/fib.hpp"
27
28#include "adjacency-list.hpp"
29#include "conf-parameter.hpp"
30
31namespace nlsr {
32namespace test {
33
34using ndn::DummyFace;
35using ndn::shared_ptr;
36
37class FibFixture : public BaseFixture
38{
39public:
40 FibFixture()
41 : face(ndn::makeDummyFace())
42 , interests(face->m_sentInterests)
43 {
44 INIT_LOGGERS("/tmp", "DEBUG");
45
46 Adjacent neighbor1(router1Name, router1FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
47 adjacencies.insert(neighbor1);
48
49 Adjacent neighbor2(router2Name, router2FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
50 adjacencies.insert(neighbor2);
51
52 Adjacent neighbor3(router3Name, router3FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
53 adjacencies.insert(neighbor3);
54
55 conf.setMaxFacesPerPrefix(2);
56
57 fib = ndn::make_shared<Fib>(ndn::ref(*face), ndn::ref(g_scheduler),ndn::ref(adjacencies),
58 ndn::ref(conf));
59
60 fib->m_faceMap.update(router1FaceUri, router1FaceId);
61 fib->m_faceMap.update(router2FaceUri, router2FaceId);
62 fib->m_faceMap.update(router3FaceUri, router3FaceId);
63 }
64
65public:
66 shared_ptr<ndn::DummyFace> face;
67 shared_ptr<Fib> fib;
68
69 AdjacencyList adjacencies;
70 ConfParameter conf;
71 std::vector<ndn::Interest>& interests;
72
73 static const ndn::Name router1Name;
74 static const ndn::Name router2Name;
75 static const ndn::Name router3Name;
76
77 static const std::string router1FaceUri;
78 static const std::string router2FaceUri;
79 static const std::string router3FaceUri;
80
81 static const uint32_t router1FaceId;
82 static const uint32_t router2FaceId;
83 static const uint32_t router3FaceId;
84};
85
86const ndn::Name FibFixture::router1Name = "/ndn/router1";
87const ndn::Name FibFixture::router2Name = "/ndn/router2";
88const ndn::Name FibFixture::router3Name = "/ndn/router3";
89
90const std::string FibFixture::router1FaceUri = "uri://face1";
91const std::string FibFixture::router2FaceUri = "uri://face2";
92const std::string FibFixture::router3FaceUri = "uri://face3";
93
94const uint32_t FibFixture::router1FaceId = 1;
95const uint32_t FibFixture::router2FaceId = 2;
96const uint32_t FibFixture::router3FaceId = 3;
97
98BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
99
100BOOST_AUTO_TEST_CASE(NextHopsAdd)
101{
102 NextHop hop1(router1FaceUri, 10);
103 NextHop hop2(router2FaceUri, 20);
104
105 NexthopList hops;
106 hops.addNextHop(hop1);
107 hops.addNextHop(hop2);
108
109 fib->update("/ndn/name", hops);
110 face->processEvents(ndn::time::milliseconds(1));
111
112 // Should register faces 1 and 2 for /ndn/name
113 BOOST_REQUIRE_EQUAL(interests.size(), 2);
114
115 ndn::nfd::ControlParameters extractedParameters;
116 ndn::Name::Component verb;
117 std::vector<ndn::Interest>::iterator it = interests.begin();
118
119 extractRibCommandParameters(*it, verb, extractedParameters);
120
121 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
122 extractedParameters.getFaceId() == router1FaceId &&
123 verb == ndn::Name::Component("register"));
124
125 ++it;
126 extractRibCommandParameters(*it, verb, extractedParameters);
127
128 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
129 extractedParameters.getFaceId() == router2FaceId &&
130 verb == ndn::Name::Component("register"));
131}
132
133
134BOOST_AUTO_TEST_CASE(NextHopsNoChange)
135{
136 NextHop hop1(router1FaceUri, 10);
137 NextHop hop2(router2FaceUri, 20);
138
139 NexthopList oldHops;
140 oldHops.addNextHop(hop1);
141 oldHops.addNextHop(hop2);
142
143 fib->update("/ndn/name", oldHops);
144 face->processEvents(ndn::time::milliseconds(1));
145
146 BOOST_REQUIRE_EQUAL(interests.size(), 2);
147 interests.clear();
148
149 fib->update("/ndn/name", oldHops);
150 face->processEvents(ndn::time::milliseconds(1));
151
152 // Should register face 1 and 2 for /ndn/name
153 BOOST_REQUIRE_EQUAL(interests.size(), 2);
154
155 ndn::nfd::ControlParameters extractedParameters;
156 ndn::Name::Component verb;
157 std::vector<ndn::Interest>::iterator it = interests.begin();
158
159 extractRibCommandParameters(*it, verb, extractedParameters);
160
161 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
162 extractedParameters.getFaceId() == router1FaceId &&
163 verb == ndn::Name::Component("register"));
164
165 ++it;
166 extractRibCommandParameters(*it, verb, extractedParameters);
167
168 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
169 extractedParameters.getFaceId() == router2FaceId &&
170 verb == ndn::Name::Component("register"));
171}
172
173BOOST_AUTO_TEST_CASE(NextHopsRemoveAll)
174{
175 NextHop hop1(router1FaceUri, 10);
176 NextHop hop2(router2FaceUri, 20);
177
178 NexthopList oldHops;
179 oldHops.addNextHop(hop1);
180 oldHops.addNextHop(hop2);
181
182 fib->update("/ndn/name", oldHops);
183 face->processEvents(ndn::time::milliseconds(1));
184
185 BOOST_REQUIRE_EQUAL(interests.size(), 2);
186 interests.clear();
187
188 NexthopList empty;
189
190 fib->update("/ndn/name", empty);
191 face->processEvents(ndn::time::milliseconds(1));
192
193 // Should unregister faces 1 and 2 for /ndn/name
194 BOOST_CHECK_EQUAL(interests.size(), 2);
195
196 ndn::nfd::ControlParameters extractedParameters;
197 ndn::Name::Component verb;
198 std::vector<ndn::Interest>::iterator it = interests.begin();
199
200 extractRibCommandParameters(*it, verb, extractedParameters);
201
202 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
203 extractedParameters.getFaceId() == router1FaceId &&
204 verb == ndn::Name::Component("unregister"));
205
206 ++it;
207 extractRibCommandParameters(*it, verb, extractedParameters);
208
209 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
210 extractedParameters.getFaceId() == router2FaceId &&
211 verb == ndn::Name::Component("unregister"));
212}
213
214BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixes)
215{
216 NextHop hop1(router1FaceUri, 10);
217 NextHop hop2(router2FaceUri, 20);
218 NextHop hop3(router3FaceUri, 30);
219
220 NexthopList hops;
221 hops.addNextHop(hop1);
222 hops.addNextHop(hop2);
223 hops.addNextHop(hop3);
224
225 fib->update("/ndn/name", hops);
226 face->processEvents(ndn::time::milliseconds(1));
227
228 // Should only register faces 1 and 2 for /ndn/name
229 BOOST_CHECK_EQUAL(interests.size(), 2);
230
231 ndn::nfd::ControlParameters extractedParameters;
232 ndn::Name::Component verb;
233 std::vector<ndn::Interest>::iterator it = interests.begin();
234
235 extractRibCommandParameters(*it, verb, extractedParameters);
236
237 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
238 extractedParameters.getFaceId() == router1FaceId &&
239 verb == ndn::Name::Component("register"));
240
241 ++it;
242 extractRibCommandParameters(*it, verb, extractedParameters);
243
244 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
245 extractedParameters.getFaceId() == router2FaceId &&
246 verb == ndn::Name::Component("register"));
247}
248
249BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixesAfterRecalculation)
250{
251 NextHop hop1(router1FaceUri, 10);
252 NextHop hop2(router2FaceUri, 20);
253
254 NexthopList hops;
255 hops.addNextHop(hop1);
256 hops.addNextHop(hop2);
257
258 fib->update("/ndn/name", hops);
259 face->processEvents(ndn::time::milliseconds(1));
260
261 // FIB
262 // Name NextHops
263 // /ndn/name (faceId=1, cost=10), (faceId=2, cost=20)
264 BOOST_REQUIRE_EQUAL(interests.size(), 2);
265 interests.clear();
266
267 // Routing table is recalculated; a new more optimal path is found
268 NextHop hop3(router3FaceUri, 5);
269 hops.addNextHop(hop3);
270
271 fib->update("/ndn/name", hops);
272 face->processEvents(ndn::time::milliseconds(1));
273
274 // To maintain a max 2 face requirement, face 3 should be registered and face 2 should be
275 // unregistered. Face 1 will also be re-registered.
276 //
277 // FIB
278 // Name NextHops
279 // /ndn/name (faceId=3, cost=5), (faceId=1, cost=10)
280
281 BOOST_CHECK_EQUAL(interests.size(), 3);
282
283 ndn::nfd::ControlParameters extractedParameters;
284 ndn::Name::Component verb;
285 std::vector<ndn::Interest>::iterator it = interests.begin();
286
287 extractRibCommandParameters(*it, verb, extractedParameters);
288
289 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
290 extractedParameters.getFaceId() == router3FaceId &&
291 verb == ndn::Name::Component("register"));
292
293 ++it;
294 extractRibCommandParameters(*it, verb, extractedParameters);
295
296 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
297 extractedParameters.getFaceId() == router1FaceId &&
298 verb == ndn::Name::Component("register"));
299
300 ++it;
301 extractRibCommandParameters(*it, verb, extractedParameters);
302
303 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
304 extractedParameters.getFaceId() == router2FaceId &&
305 verb == ndn::Name::Component("unregister"));
306}
307
308BOOST_AUTO_TEST_SUITE_END()
309
310} //namespace test
311} //namespace nlsr