blob: 5e942d2c6987816fc0cf25dd50f67b2722e97872 [file] [log] [blame]
Junxiao Shicde37ad2015-12-24 01:02:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi84d62cb2017-07-12 16:15:18 +00002/*
Junxiao Shi7003c602017-01-10 13:35:28 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shicde37ad2015-12-24 01:02:05 -07004 * 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.
10 *
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/>.
24 */
25
26#include "face/ethernet-factory.hpp"
Junxiao Shi7003c602017-01-10 13:35:28 +000027#include "face/face.hpp"
Junxiao Shicde37ad2015-12-24 01:02:05 -070028
Junxiao Shi7003c602017-01-10 13:35:28 +000029#include "ethernet-fixture.hpp"
30#include "face-system-fixture.hpp"
Junxiao Shi79a92082017-08-08 02:40:59 +000031#include "factory-test-common.hpp"
Davide Pesaventob15276f2017-07-15 16:27:13 -040032
Junxiao Shi7003c602017-01-10 13:35:28 +000033#include <boost/algorithm/string/replace.hpp>
34#include <boost/range/algorithm/count_if.hpp>
Junxiao Shicde37ad2015-12-24 01:02:05 -070035
36namespace nfd {
Junxiao Shi7003c602017-01-10 13:35:28 +000037namespace face {
Junxiao Shicde37ad2015-12-24 01:02:05 -070038namespace tests {
39
Junxiao Shi0ba6d642017-07-17 00:53:22 +000040class EthernetFactoryFixture : public EthernetFixture
41 , public FaceSystemFactoryFixture<EthernetFactory>
Junxiao Shi7003c602017-01-10 13:35:28 +000042{
Junxiao Shi0ba6d642017-07-17 00:53:22 +000043protected:
Junxiao Shi79a92082017-08-08 02:40:59 +000044 EthernetFactoryFixture()
45 {
46 this->copyRealNetifsToNetmon();
47 }
48
Davide Pesaventob15276f2017-07-15 16:27:13 -040049 std::set<std::string>
50 listUrisOfAvailableNetifs() const
51 {
52 std::set<std::string> uris;
53 std::transform(netifs.begin(), netifs.end(), std::inserter(uris, uris.end()),
54 [] (const shared_ptr<const ndn::net::NetworkInterface>& ni) {
55 return FaceUri::fromDev(ni->getName()).toString();
56 });
57 return uris;
58 }
59
Junxiao Shi7003c602017-01-10 13:35:28 +000060 std::vector<const Face*>
Teng Liangbfea5752017-03-29 04:51:10 +000061 listEtherMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
Junxiao Shi7003c602017-01-10 13:35:28 +000062 {
Teng Liangbfea5752017-03-29 04:51:10 +000063 return this->listFacesByScheme("ether", linkType);
Junxiao Shi7003c602017-01-10 13:35:28 +000064 }
65
66 size_t
Teng Liangbfea5752017-03-29 04:51:10 +000067 countEtherMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
Junxiao Shi7003c602017-01-10 13:35:28 +000068 {
Teng Liangbfea5752017-03-29 04:51:10 +000069 return this->listEtherMcastFaces(linkType).size();
Junxiao Shi7003c602017-01-10 13:35:28 +000070 }
71};
72
Junxiao Shi0ba6d642017-07-17 00:53:22 +000073BOOST_AUTO_TEST_SUITE(Face)
74BOOST_FIXTURE_TEST_SUITE(TestEthernetFactory, EthernetFactoryFixture)
75
76using nfd::Face;
77
78BOOST_AUTO_TEST_SUITE(ProcessConfig)
Junxiao Shi7003c602017-01-10 13:35:28 +000079
Davide Pesaventob15276f2017-07-15 16:27:13 -040080BOOST_AUTO_TEST_CASE(ListeningChannels)
Junxiao Shi7003c602017-01-10 13:35:28 +000081{
82 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
83
84 const std::string CONFIG = R"CONFIG(
85 face_system
86 {
87 ether
88 {
Davide Pesaventob15276f2017-07-15 16:27:13 -040089 listen yes
90 idle_timeout 60
91 mcast no
92 }
93 }
94 )CONFIG";
95
96 parseConfig(CONFIG, true);
97 parseConfig(CONFIG, false);
98
99 auto& factory = this->getFactoryById<EthernetFactory>("ether");
100 checkChannelListEqual(factory, this->listUrisOfAvailableNetifs());
101 for (const auto& channel : factory.getChannels()) {
102 BOOST_CHECK_EQUAL(channel->isListening(), true);
103 }
104
105 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), 0);
106}
107
108BOOST_AUTO_TEST_CASE(NonListeningChannels)
109{
110 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
111
112 const std::string CONFIG = R"CONFIG(
113 face_system
114 {
115 ether
116 {
117 listen no
118 idle_timeout 60
119 mcast no
120 }
121 }
122 )CONFIG";
123
124 parseConfig(CONFIG, true);
125 parseConfig(CONFIG, false);
126
127 auto& factory = this->getFactoryById<EthernetFactory>("ether");
128 checkChannelListEqual(factory, this->listUrisOfAvailableNetifs());
129 for (const auto& channel : factory.getChannels()) {
130 BOOST_CHECK_EQUAL(channel->isListening(), false);
131 }
132
133 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), 0);
134}
135
136BOOST_AUTO_TEST_CASE(BadListen)
137{
138 const std::string CONFIG = R"CONFIG(
139 face_system
140 {
141 ether
142 {
143 listen hello
144 }
145 }
146 )CONFIG";
147
148 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
149 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
150}
151
152BOOST_AUTO_TEST_CASE(McastNormal)
153{
154 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
155
156 const std::string CONFIG = R"CONFIG(
157 face_system
158 {
159 ether
160 {
161 listen no
Junxiao Shi7003c602017-01-10 13:35:28 +0000162 mcast yes
163 mcast_group 01:00:5E:00:17:AA
Teng Liangbfea5752017-03-29 04:51:10 +0000164 mcast_ad_hoc no
Junxiao Shi7003c602017-01-10 13:35:28 +0000165 whitelist
166 {
167 *
168 }
169 blacklist
170 {
171 }
172 }
173 }
174 )CONFIG";
175
Junxiao Shi1b65ca12017-01-21 23:04:41 +0000176 parseConfig(CONFIG, true);
177 parseConfig(CONFIG, false);
Junxiao Shi7003c602017-01-10 13:35:28 +0000178
179 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), netifs.size());
180}
181
Teng Liangbfea5752017-03-29 04:51:10 +0000182BOOST_AUTO_TEST_CASE(EnableDisableMcast)
Junxiao Shi7003c602017-01-10 13:35:28 +0000183{
Teng Liangbfea5752017-03-29 04:51:10 +0000184 const std::string CONFIG_WITH_MCAST = R"CONFIG(
Junxiao Shi7003c602017-01-10 13:35:28 +0000185 face_system
186 {
Teng Liangbfea5752017-03-29 04:51:10 +0000187 ether
188 {
Davide Pesaventob15276f2017-07-15 16:27:13 -0400189 listen no
Teng Liangbfea5752017-03-29 04:51:10 +0000190 mcast yes
191 }
192 }
193 )CONFIG";
194 const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
195 face_system
196 {
197 ether
198 {
Davide Pesaventob15276f2017-07-15 16:27:13 -0400199 listen no
Teng Liangbfea5752017-03-29 04:51:10 +0000200 mcast no
201 }
Junxiao Shi7003c602017-01-10 13:35:28 +0000202 }
203 )CONFIG";
204
Teng Liangbfea5752017-03-29 04:51:10 +0000205 parseConfig(CONFIG_WITHOUT_MCAST, false);
Junxiao Shi7003c602017-01-10 13:35:28 +0000206 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), 0);
Teng Liangbfea5752017-03-29 04:51:10 +0000207
208 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
209
210 parseConfig(CONFIG_WITH_MCAST, false);
211 g_io.poll();
212 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), netifs.size());
213
214 parseConfig(CONFIG_WITHOUT_MCAST, false);
215 g_io.poll();
216 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), 0);
217}
218
219BOOST_AUTO_TEST_CASE(McastAdHoc)
220{
221 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
222
223 const std::string CONFIG = R"CONFIG(
224 face_system
225 {
226 ether
227 {
Davide Pesaventob15276f2017-07-15 16:27:13 -0400228 listen no
229 mcast yes
Teng Liangbfea5752017-03-29 04:51:10 +0000230 mcast_ad_hoc yes
231 }
232 }
233 )CONFIG";
234
235 parseConfig(CONFIG, false);
Davide Pesaventob15276f2017-07-15 16:27:13 -0400236 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(ndn::nfd::LINK_TYPE_MULTI_ACCESS), 0);
Teng Liangbfea5752017-03-29 04:51:10 +0000237 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(ndn::nfd::LINK_TYPE_AD_HOC), netifs.size());
238}
239
240BOOST_AUTO_TEST_CASE(ChangeMcastGroup)
241{
242 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
243
244 const std::string CONFIG1 = R"CONFIG(
245 face_system
246 {
247 ether
248 {
Davide Pesavento43ff2a92017-05-18 19:50:57 -0400249 mcast_group 01:00:5e:90:10:01
Teng Liangbfea5752017-03-29 04:51:10 +0000250 }
251 }
252 )CONFIG";
253 const std::string CONFIG2 = R"CONFIG(
254 face_system
255 {
256 ether
257 {
Davide Pesavento43ff2a92017-05-18 19:50:57 -0400258 mcast_group 01:00:5e:90:10:02
Teng Liangbfea5752017-03-29 04:51:10 +0000259 }
260 }
261 )CONFIG";
262
263 parseConfig(CONFIG1, false);
264 auto etherMcastFaces = this->listEtherMcastFaces();
265 BOOST_REQUIRE_EQUAL(etherMcastFaces.size(), netifs.size());
266 BOOST_CHECK_EQUAL(etherMcastFaces.front()->getRemoteUri(),
Davide Pesavento43ff2a92017-05-18 19:50:57 -0400267 FaceUri(ethernet::Address{0x01, 0x00, 0x5e, 0x90, 0x10, 0x01}));
Teng Liangbfea5752017-03-29 04:51:10 +0000268
269 parseConfig(CONFIG2, false);
270 g_io.poll();
271 etherMcastFaces = this->listEtherMcastFaces();
272 BOOST_REQUIRE_EQUAL(etherMcastFaces.size(), netifs.size());
273 BOOST_CHECK_EQUAL(etherMcastFaces.front()->getRemoteUri(),
Davide Pesavento43ff2a92017-05-18 19:50:57 -0400274 FaceUri(ethernet::Address{0x01, 0x00, 0x5e, 0x90, 0x10, 0x02}));
Junxiao Shi7003c602017-01-10 13:35:28 +0000275}
276
277BOOST_AUTO_TEST_CASE(Whitelist)
278{
279 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
280
281 std::string CONFIG = R"CONFIG(
282 face_system
283 {
284 ether
285 {
286 whitelist
287 {
288 ifname %ifname
289 }
290 }
291 }
292 )CONFIG";
Davide Pesaventob15276f2017-07-15 16:27:13 -0400293 auto ifname = netifs.front()->getName();
294 boost::replace_first(CONFIG, "%ifname", ifname);
Junxiao Shi7003c602017-01-10 13:35:28 +0000295
Junxiao Shi1b65ca12017-01-21 23:04:41 +0000296 parseConfig(CONFIG, false);
Davide Pesaventob15276f2017-07-15 16:27:13 -0400297
Junxiao Shi7003c602017-01-10 13:35:28 +0000298 auto etherMcastFaces = this->listEtherMcastFaces();
299 BOOST_REQUIRE_EQUAL(etherMcastFaces.size(), 1);
Davide Pesaventob15276f2017-07-15 16:27:13 -0400300 BOOST_CHECK_EQUAL(etherMcastFaces.front()->getLocalUri(), FaceUri::fromDev(ifname));
Junxiao Shi7003c602017-01-10 13:35:28 +0000301}
302
303BOOST_AUTO_TEST_CASE(Blacklist)
304{
305 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
306
307 std::string CONFIG = R"CONFIG(
308 face_system
309 {
310 ether
311 {
312 blacklist
313 {
314 ifname %ifname
315 }
316 }
317 }
318 )CONFIG";
Davide Pesaventob15276f2017-07-15 16:27:13 -0400319 auto ifname = netifs.front()->getName();
320 boost::replace_first(CONFIG, "%ifname", ifname);
Junxiao Shi7003c602017-01-10 13:35:28 +0000321
Junxiao Shi1b65ca12017-01-21 23:04:41 +0000322 parseConfig(CONFIG, false);
Davide Pesaventob15276f2017-07-15 16:27:13 -0400323
Junxiao Shi7003c602017-01-10 13:35:28 +0000324 auto etherMcastFaces = this->listEtherMcastFaces();
325 BOOST_CHECK_EQUAL(etherMcastFaces.size(), netifs.size() - 1);
Davide Pesaventob15276f2017-07-15 16:27:13 -0400326 BOOST_CHECK_EQUAL(boost::count_if(etherMcastFaces, [ifname] (const Face* face) {
327 return face->getLocalUri() == FaceUri::fromDev(ifname);
Junxiao Shi7003c602017-01-10 13:35:28 +0000328 }), 0);
329}
330
Teng Liangbfea5752017-03-29 04:51:10 +0000331BOOST_AUTO_TEST_CASE(Omitted)
Junxiao Shi7003c602017-01-10 13:35:28 +0000332{
Teng Liangbfea5752017-03-29 04:51:10 +0000333 const std::string CONFIG = R"CONFIG(
Junxiao Shi7003c602017-01-10 13:35:28 +0000334 face_system
335 {
Junxiao Shi7003c602017-01-10 13:35:28 +0000336 }
337 )CONFIG";
338
Teng Liangbfea5752017-03-29 04:51:10 +0000339 parseConfig(CONFIG, true);
340 parseConfig(CONFIG, false);
341
Junxiao Shi7003c602017-01-10 13:35:28 +0000342 BOOST_CHECK_EQUAL(this->countEtherMcastFaces(), 0);
Junxiao Shi7003c602017-01-10 13:35:28 +0000343}
344
345BOOST_AUTO_TEST_CASE(BadMcast)
346{
347 const std::string CONFIG = R"CONFIG(
348 face_system
349 {
350 ether
351 {
352 mcast hello
353 }
354 }
355 )CONFIG";
356
357 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
358 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
359}
360
361BOOST_AUTO_TEST_CASE(BadMcastGroup)
362{
363 const std::string CONFIG = R"CONFIG(
364 face_system
365 {
366 ether
367 {
368 mcast yes
369 mcast_group hello
370 }
371 }
372 )CONFIG";
373
374 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
375 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
376}
377
378BOOST_AUTO_TEST_CASE(UnicastMcastGroup)
379{
380 const std::string CONFIG = R"CONFIG(
381 face_system
382 {
383 ether
384 {
385 mcast yes
Davide Pesavento43ff2a92017-05-18 19:50:57 -0400386 mcast_group 00:00:5e:00:53:5e
Junxiao Shi7003c602017-01-10 13:35:28 +0000387 }
388 }
389 )CONFIG";
390
391 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
392 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
393}
394
395BOOST_AUTO_TEST_CASE(UnknownOption)
396{
397 const std::string CONFIG = R"CONFIG(
398 face_system
399 {
400 ether
401 {
402 hello
403 }
404 }
405 )CONFIG";
406
407 BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
408 BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
409}
410
411BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
Junxiao Shicde37ad2015-12-24 01:02:05 -0700412
413BOOST_AUTO_TEST_CASE(GetChannels)
414{
Davide Pesaventob15276f2017-07-15 16:27:13 -0400415 BOOST_CHECK_EQUAL(factory.getChannels().empty(), true);
416 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
417
418 factory.createChannel(netifs.front(), time::minutes(1));
419 checkChannelListEqual(factory, {FaceUri::fromDev(netifs.front()->getName()).toString()});
Junxiao Shicde37ad2015-12-24 01:02:05 -0700420}
421
Davide Pesaventob15276f2017-07-15 16:27:13 -0400422BOOST_AUTO_TEST_CASE(CreateChannel)
423{
424 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
425
426 auto channel1 = factory.createChannel(netifs.front(), time::minutes(1));
427 auto channel1a = factory.createChannel(netifs.front(), time::minutes(5));
428 BOOST_CHECK_EQUAL(channel1, channel1a);
429 BOOST_CHECK_EQUAL(channel1->getUri().toString(), "dev://" + netifs.front()->getName());
430
431 SKIP_IF_ETHERNET_NETIF_COUNT_LT(2);
432
433 auto channel2 = factory.createChannel(netifs.back(), time::minutes(1));
434 BOOST_CHECK_NE(channel1, channel2);
435}
436
437BOOST_AUTO_TEST_CASE(CreateFace)
438{
439 createFace(factory,
440 FaceUri("ether://[00:00:5e:00:53:5e]"),
441 FaceUri("dev://eth0"),
442 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
443 false,
444 {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
445
446 SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
447 auto localUri = factory.createChannel(netifs.front(), time::minutes(1))->getUri();
448
449 createFace(factory,
450 FaceUri("ether://[00:00:5e:00:53:5e]"),
451 localUri,
452 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
453 false,
454 {CreateFaceExpectedResult::SUCCESS, 0, ""});
455
456 createFace(factory,
457 FaceUri("ether://[00:00:5e:00:53:5e]"),
458 localUri,
459 ndn::nfd::FACE_PERSISTENCY_PERMANENT,
460 false,
461 {CreateFaceExpectedResult::SUCCESS, 0, ""});
462
463 createFace(factory,
464 FaceUri("ether://[00:00:5e:00:53:53]"),
465 localUri,
466 ndn::nfd::FACE_PERSISTENCY_PERMANENT,
467 false,
468 {CreateFaceExpectedResult::SUCCESS, 0, ""});
469}
470
471BOOST_AUTO_TEST_CASE(UnsupportedCreateFace)
Junxiao Shicde37ad2015-12-24 01:02:05 -0700472{
Eric Newberry42602412016-08-27 09:33:18 -0700473 createFace(factory,
Davide Pesavento46afec42017-05-28 14:28:47 -0400474 FaceUri("ether://[00:00:5e:00:53:5e]"),
Eric Newberry78e32b02017-04-01 14:34:44 +0000475 {},
Eric Newberry42602412016-08-27 09:33:18 -0700476 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
Eric Newberryf40551a2016-09-05 15:41:16 -0700477 false,
Davide Pesavento46afec42017-05-28 14:28:47 -0400478 {CreateFaceExpectedResult::FAILURE, 406,
479 "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme"});
480
481 createFace(factory,
482 FaceUri("ether://[00:00:5e:00:53:5e]"),
483 FaceUri("udp4://127.0.0.1:20071"),
484 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
485 false,
486 {CreateFaceExpectedResult::FAILURE, 406,
487 "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme"});
488
489 createFace(factory,
490 FaceUri("ether://[00:00:5e:00:53:5e]"),
491 FaceUri("dev://eth0"),
492 ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
493 false,
494 {CreateFaceExpectedResult::FAILURE, 406,
495 "Outgoing Ethernet faces do not support on-demand persistency"});
496
497 createFace(factory,
498 FaceUri("ether://[01:00:5e:90:10:5e]"),
499 FaceUri("dev://eth0"),
500 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
501 false,
502 {CreateFaceExpectedResult::FAILURE, 406,
503 "Cannot create multicast Ethernet faces"});
504
505 createFace(factory,
506 FaceUri("ether://[00:00:5e:00:53:5e]"),
507 FaceUri("dev://eth0"),
508 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
509 true,
510 {CreateFaceExpectedResult::FAILURE, 406,
511 "Local fields can only be enabled on faces with local scope"});
Junxiao Shicde37ad2015-12-24 01:02:05 -0700512}
513
514BOOST_AUTO_TEST_SUITE_END() // TestEthernetFactory
515BOOST_AUTO_TEST_SUITE_END() // Face
516
517} // namespace tests
Junxiao Shi7003c602017-01-10 13:35:28 +0000518} // namespace face
Junxiao Shicde37ad2015-12-24 01:02:05 -0700519} // namespace nfd