blob: fec1f636ecd11dfc7eac343f43494b68e25b3963 [file] [log] [blame]
Steve DiBenedetto042bfe92014-01-30 15:05:08 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "mgmt/fib-manager.hpp"
8#include "fw/forwarder.hpp"
9#include "table/fib.hpp"
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070010#include "table/fib-nexthop.hpp"
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070011#include "face/face.hpp"
Steve DiBenedetto3970c892014-01-31 23:31:13 -070012#include "mgmt/internal-face.hpp"
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070013#include "../face/dummy-face.hpp"
14
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070015#include <algorithm>
16
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070017#include <ndn-cpp-dev/management/fib-management-options.hpp>
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070018#include <ndn-cpp-dev/management/control-response.hpp>
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070019
20#include <boost/test/unit_test.hpp>
21
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070022namespace nfd {
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070023
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070024NFD_LOG_INIT("FibManagerTest");
25
26class FibManagerFixture
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070027{
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070028public:
29
30 shared_ptr<Face>
31 getFace(FaceId id)
32 {
Steve DiBenedetto80ddc212014-02-01 22:23:56 -070033 if (id > 0 && id <= m_faces.size())
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070034 {
Steve DiBenedetto80ddc212014-02-01 22:23:56 -070035 return m_faces[id-1];
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070036 }
Steve DiBenedetto80ddc212014-02-01 22:23:56 -070037 NFD_LOG_DEBUG("No face found returning NULL");
38 return shared_ptr<DummyFace>();
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070039 }
40
41 void
42 addFace(shared_ptr<Face> face)
43 {
44 m_faces.push_back(face);
45 }
46
47private:
48 std::vector<shared_ptr<Face> > m_faces;
49};
50
51
52BOOST_AUTO_TEST_SUITE(MgmtFibManager)
53
54void
55validateControlResponse(const Data& response,
56 uint32_t expectedCode,
57 const std::string& expectedText)
58{
59 Block controlRaw = response.getContent().blockFromValue();
60
61 ndn::ControlResponse control;
62 control.wireDecode(controlRaw);
63
64 NFD_LOG_DEBUG("received control response"
65 << " Name: " << response.getName()
66 << " code: " << control.getCode()
67 << " text: " << control.getText());
68
69 BOOST_REQUIRE(control.getCode() == expectedCode);
70 BOOST_REQUIRE(control.getText() == expectedText);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -070071}
72
Steve DiBenedetto80ddc212014-02-01 22:23:56 -070073bool
74foundNextHop(FaceId id, uint32_t cost, const fib::NextHop& next)
75{
76 return id == next.getFace()->getId() && next.getCost() == cost;
77}
78
79bool
80addedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
81{
82 shared_ptr<fib::Entry> entry = fib.findLongestPrefixMatch(prefix);
83
84 if (entry)
85 {
86 const fib::NextHopList& hops = entry->getNextHops();
87 return hops.size() == oldSize + 1 &&
88 std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) != hops.end();
89 }
90 return false;
91}
92
93BOOST_AUTO_TEST_CASE(TestFireInterestFilter)
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070094{
95 FibManagerFixture fixture;
Steve DiBenedetto80ddc212014-02-01 22:23:56 -070096 shared_ptr<InternalFace> face(make_shared<InternalFace>());
Steve DiBenedetto43cd0372014-02-01 17:05:07 -070097 Fib fib;
98 FibManager manager(fib,
99 bind(&FibManagerFixture::getFace,
100 &fixture, _1),
101 face);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700102
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700103 face->onReceiveData +=
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700104 bind(&validateControlResponse, _1, 400, "MALFORMED");
105
106 Interest command("/localhost/nfd/fib");
107 face->sendInterest(command);
108}
109
110BOOST_AUTO_TEST_CASE(MalformedCommmand)
111{
112 FibManagerFixture fixture;
113 shared_ptr<InternalFace> face(make_shared<InternalFace>());
114 Fib fib;
115 FibManager manager(fib,
116 bind(&FibManagerFixture::getFace,
117 &fixture, _1),
118 face);
119
120 face->onReceiveData +=
121 bind(&validateControlResponse, _1, 400, "MALFORMED");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700122
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700123 Interest command("/localhost/nfd/fib");
124 manager.onFibRequest(command);
125}
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700126
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700127BOOST_AUTO_TEST_CASE(UnsupportedVerb)
128{
129 FibManagerFixture fixture;
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700130 shared_ptr<InternalFace> face(make_shared<InternalFace>());
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700131 Fib fib;
132 FibManager manager(fib,
133 bind(&FibManagerFixture::getFace,
134 &fixture, _1),
135 face);
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700136
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700137 face->onReceiveData +=
138 bind(&validateControlResponse, _1, 404, "UNSUPPORTED");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700139
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700140 ndn::FibManagementOptions options;
141 options.setName("/hello");
142 options.setFaceId(1);
143 options.setCost(1);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700144
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700145 Block encodedOptions(options.wireEncode());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700146
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700147 Name commandName("/localhost/nfd/fib");
148 commandName.append("unsupported");
149 commandName.append(encodedOptions);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700150
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700151 Interest command(commandName);
152 manager.onFibRequest(command);
153}
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700154
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700155BOOST_AUTO_TEST_CASE(UnsignedCommand)
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700156{
157 FibManagerFixture fixture;
158 fixture.addFace(make_shared<DummyFace>());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700159
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700160 shared_ptr<InternalFace> face(make_shared<InternalFace>());
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700161 Fib fib;
162 FibManager manager(fib,
163 bind(&FibManagerFixture::getFace,
164 &fixture, _1),
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700165 face);
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700166 face->onReceiveData +=
167 bind(&validateControlResponse, _1, 200, "OK");
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700168 /// \todo enable once sig checking implement
169 // bind(&validateControlResponse, _1, 401, "SIGREG");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700170
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700171 ndn::FibManagementOptions options;
172 options.setName("/hello");
173 options.setFaceId(1);
174 options.setCost(101);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700175
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700176 Block encodedOptions(options.wireEncode());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700177
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700178 Name commandName("/localhost/nfd/fib");
179 commandName.append("add-nexthop");
180 commandName.append(encodedOptions);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700181
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700182 Interest command(commandName);
183 manager.onFibRequest(command);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700184
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700185 BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101));
186}
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700187
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700188BOOST_AUTO_TEST_CASE(UnauthorizedCommand)
189{
190 FibManagerFixture fixture;
191 fixture.addFace(make_shared<DummyFace>());
192
193 shared_ptr<InternalFace> face(make_shared<InternalFace>());
194 Fib fib;
195 FibManager manager(fib,
196 bind(&FibManagerFixture::getFace,
197 &fixture, _1),
198 face);
199 face->onReceiveData +=
200 bind(&validateControlResponse, _1, 200, "OK");
201 /// \todo enable once sig checking implement
202 // bind(&validateControlResponse, _1, 403, "UNAUTHORIZED");
203
204 ndn::FibManagementOptions options;
205 options.setName("/hello");
206 options.setFaceId(1);
207 options.setCost(101);
208
209 Block encodedOptions(options.wireEncode());
210
211 Name commandName("/localhost/nfd/fib");
212 commandName.append("add-nexthop");
213 commandName.append(encodedOptions);
214
215 Interest command(commandName);
216 manager.onFibRequest(command);
217
218 BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101));
219}
220
221BOOST_AUTO_TEST_CASE(BadOptionParse)
222{
223 FibManagerFixture fixture;
224 fixture.addFace(make_shared<DummyFace>());
225
226 shared_ptr<InternalFace> face(make_shared<InternalFace>());
227 Fib fib;
228 FibManager manager(fib,
229 bind(&FibManagerFixture::getFace,
230 &fixture, _1),
231 face);
232
233 face->onReceiveData +=
234 bind(&validateControlResponse, _1, 400, "MALFORMED");
235
236 Name commandName("/localhost/nfd/fib");
237 commandName.append("add-nexthop");
238 commandName.append("NotReallyOptions");
239
240 Interest command(commandName);
241 manager.onFibRequest(command);
242}
243
244BOOST_AUTO_TEST_CASE(UnknownFaceId)
245{
246 FibManagerFixture fixture;
247 fixture.addFace(make_shared<DummyFace>());
248
249 shared_ptr<InternalFace> face(make_shared<InternalFace>());
250 Fib fib;
251 FibManager manager(fib,
252 bind(&FibManagerFixture::getFace,
253 &fixture, _1),
254 face);
255
256 face->onReceiveData +=
257 bind(&validateControlResponse, _1, 400, "MALFORMED");
258
259 ndn::FibManagementOptions options;
260 options.setName("/hello");
261 options.setFaceId(1000);
262 options.setCost(101);
263
264 Block encodedOptions(options.wireEncode());
265
266 Name commandName("/localhost/nfd/fib");
267 commandName.append("add-nexthop");
268 commandName.append(encodedOptions);
269
270 Interest command(commandName);
271 manager.onFibRequest(command);
272
273 BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101) == false);
274}
275
276BOOST_AUTO_TEST_CASE(AddNextHopVerbInitialAdd)
277{
278 FibManagerFixture fixture;
279 fixture.addFace(make_shared<DummyFace>());
280
281 shared_ptr<InternalFace> face(make_shared<InternalFace>());
282 Fib fib;
283 FibManager manager(fib,
284 bind(&FibManagerFixture::getFace,
285 &fixture, _1),
286 face);
287 face->onReceiveData +=
288 bind(&validateControlResponse, _1, 200, "OK");
289
290 ndn::FibManagementOptions options;
291 options.setName("/hello");
292 options.setFaceId(1);
293 options.setCost(101);
294
295 Block encodedOptions(options.wireEncode());
296
297 Name commandName("/localhost/nfd/fib");
298 commandName.append("add-nexthop");
299 commandName.append(encodedOptions);
300
301 Interest command(commandName);
302 manager.onFibRequest(command);
303
304 BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101));
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700305}
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700306
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700307BOOST_AUTO_TEST_CASE(AddNextHopVerbAddToExisting)
308{
309 FibManagerFixture fixture;
310 fixture.addFace(make_shared<DummyFace>());
311 fixture.addFace(make_shared<DummyFace>());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700312
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700313 shared_ptr<InternalFace> face(make_shared<InternalFace>());
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700314 Fib fib;
315 FibManager manager(fib,
316 bind(&FibManagerFixture::getFace,
317 &fixture, _1),
318 face);
319 face->onReceiveData +=
320 bind(&validateControlResponse, _1, 200, "OK");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700321
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700322 // Add faces with cost == FaceID for the name /hello
323 // This test assumes:
324 // FaceIDs are -1 because we don't add them to a forwarder
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700325
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700326 for (int i = 1; i <= 2; i++)
327 {
328 ndn::FibManagementOptions options;
329 options.setName("/hello");
330 options.setFaceId(i);
331 options.setCost(100 + i);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700332
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700333 Block encodedOptions(options.wireEncode());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700334
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700335 Name commandName("/localhost/nfd/fib");
336 commandName.append("add-nexthop");
337 commandName.append(encodedOptions);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700338
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700339 Interest command(commandName);
340 manager.onFibRequest(command);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700341
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700342 shared_ptr<fib::Entry> entry = fib.findLongestPrefixMatch("/hello");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700343
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700344 if (entry)
345 {
346 const fib::NextHopList& hops = entry->getNextHops();
347 for (int j = 1; j <= i; j++)
348 {
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700349 BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", i - 1, 100 + j));
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700350 }
351 }
352 else
353 {
354 BOOST_FAIL("Failed to find expected fib entry");
355 }
356 }
357}
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700358
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700359BOOST_AUTO_TEST_CASE(AddNextHopVerbUpdateFaceCost)
360{
361 FibManagerFixture fixture;
362 fixture.addFace(make_shared<DummyFace>());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700363
Steve DiBenedetto80ddc212014-02-01 22:23:56 -0700364 shared_ptr<InternalFace> face(make_shared<InternalFace>());
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700365 Fib fib;
366 FibManager manager(fib,
367 bind(&FibManagerFixture::getFace,
368 &fixture, _1),
369 face);
370 face->onReceiveData +=
371 bind(&validateControlResponse, _1, 200, "OK");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700372
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700373 ndn::FibManagementOptions options;
374 options.setName("/hello");
375 options.setFaceId(1);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700376
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700377 {
378 options.setCost(1);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700379
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700380 Block encodedOptions(options.wireEncode());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700381
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700382 Name commandName("/localhost/nfd/fib");
383 commandName.append("add-nexthop");
384 commandName.append(encodedOptions);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700385
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700386 Interest command(commandName);
387 manager.onFibRequest(command);
388 }
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700389
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700390 {
391 options.setCost(102);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700392
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700393 Block encodedOptions(options.wireEncode());
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700394
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700395 Name commandName("/localhost/nfd/fib");
396 commandName.append("add-nexthop");
397 commandName.append(encodedOptions);
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700398
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700399 Interest command(commandName);
400 manager.onFibRequest(command);
401 }
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700402
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700403 shared_ptr<fib::Entry> entry = fib.findLongestPrefixMatch("/hello");
Steve DiBenedetto042bfe92014-01-30 15:05:08 -0700404
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700405 // Add faces with cost == FaceID for the name /hello
406 // This test assumes:
407 // FaceIDs are -1 because we don't add them to a forwarder
408 if (entry)
409 {
410 const fib::NextHopList& hops = entry->getNextHops();
411 BOOST_REQUIRE(hops.size() == 1);
412 BOOST_REQUIRE(std::find_if(hops.begin(),
413 hops.end(),
414 bind(&foundNextHop, -1, 102, _1)) != hops.end());
415 }
416 else
417 {
418 BOOST_FAIL("Failed to find expected fib entry");
419 }
420}
Steve DiBenedetto3970c892014-01-31 23:31:13 -0700421
Steve DiBenedetto43cd0372014-02-01 17:05:07 -0700422BOOST_AUTO_TEST_SUITE_END()
423
424} // namespace nfd