blob: 4d6f053b87a45f7574179cebc39c35c6c212d881 [file] [log] [blame]
Davide Pesavento44deacc2014-02-19 10:48:07 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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/>.
Steve DiBenedettoef04f272014-06-04 14:28:31 -060024 */
Davide Pesavento44deacc2014-02-19 10:48:07 +010025
Davide Pesavento7726ae52014-11-23 21:01:05 +010026#include "face/ethernet-face.hpp"
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080027#include "face/ethernet-factory.hpp"
Davide Pesavento44deacc2014-02-19 10:48:07 +010028
Davide Pesavento7726ae52014-11-23 21:01:05 +010029#include "core/network-interface.hpp"
Davide Pesavento4c1a0782014-08-14 16:13:20 +020030#include "tests/test-common.hpp"
Davide Pesaventob60cc122014-03-19 19:26:02 +010031
Davide Pesavento7726ae52014-11-23 21:01:05 +010032#include <pcap/pcap.h>
33
Davide Pesavento44deacc2014-02-19 10:48:07 +010034namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Davide Pesavento44deacc2014-02-19 10:48:07 +010036
Davide Pesaventob60cc122014-03-19 19:26:02 +010037class InterfacesFixture : protected BaseFixture
38{
39protected:
40 InterfacesFixture()
41 {
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +030042 EthernetFactory factory;
43
Davide Pesaventob499a602014-11-18 22:36:56 +010044 for (const auto& netif : listNetworkInterfaces()) {
45 if (!netif.isLoopback() && netif.isUp()) {
46 try {
47 factory.createMulticastFace(netif, ethernet::getBroadcastAddress());
48 }
49 catch (Face::Error&) {
50 continue;
51 }
Davide Pesaventob60cc122014-03-19 19:26:02 +010052
Davide Pesaventob499a602014-11-18 22:36:56 +010053 m_interfaces.push_back(netif);
Davide Pesaventob60cc122014-03-19 19:26:02 +010054 }
Davide Pesaventob499a602014-11-18 22:36:56 +010055 }
Davide Pesaventob60cc122014-03-19 19:26:02 +010056 }
57
58protected:
Davide Pesaventob499a602014-11-18 22:36:56 +010059 std::vector<NetworkInterfaceInfo> m_interfaces;
Davide Pesaventob60cc122014-03-19 19:26:02 +010060};
61
Davide Pesavento7726ae52014-11-23 21:01:05 +010062BOOST_FIXTURE_TEST_SUITE(FaceEthernet, InterfacesFixture)
Davide Pesaventob60cc122014-03-19 19:26:02 +010063
Davide Pesavento7726ae52014-11-23 21:01:05 +010064BOOST_AUTO_TEST_CASE(GetChannels)
Davide Pesavento44deacc2014-02-19 10:48:07 +010065{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080066 EthernetFactory factory;
Davide Pesavento44deacc2014-02-19 10:48:07 +010067
Davide Pesavento7726ae52014-11-23 21:01:05 +010068 auto channels = factory.getChannels();
69 BOOST_CHECK_EQUAL(channels.empty(), true);
70}
Davide Pesavento44deacc2014-02-19 10:48:07 +010071
Davide Pesavento7726ae52014-11-23 21:01:05 +010072BOOST_AUTO_TEST_CASE(MulticastFacesMap)
73{
74 if (m_interfaces.empty()) {
75 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
76 "cannot perform MulticastFacesMap test");
77 return;
78 }
79
80 EthernetFactory factory;
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +030081 shared_ptr<EthernetFace> face1 = factory.createMulticastFace(m_interfaces.front(),
82 ethernet::getBroadcastAddress());
83 shared_ptr<EthernetFace> face1bis = factory.createMulticastFace(m_interfaces.front(),
84 ethernet::getBroadcastAddress());
Davide Pesaventob60cc122014-03-19 19:26:02 +010085 BOOST_CHECK_EQUAL(face1, face1bis);
86
Davide Pesaventob499a602014-11-18 22:36:56 +010087 if (m_interfaces.size() > 1) {
88 shared_ptr<EthernetFace> face2 = factory.createMulticastFace(m_interfaces.back(),
89 ethernet::getBroadcastAddress());
90 BOOST_CHECK_NE(face1, face2);
91 }
92 else {
Davide Pesavento7726ae52014-11-23 21:01:05 +010093 BOOST_WARN_MESSAGE(false, "Only one interface available for pcap, "
94 "cannot test second EthernetFace creation");
Davide Pesaventob499a602014-11-18 22:36:56 +010095 }
Davide Pesaventob60cc122014-03-19 19:26:02 +010096
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +030097 shared_ptr<EthernetFace> face3 = factory.createMulticastFace(m_interfaces.front(),
98 ethernet::getDefaultMulticastAddress());
Davide Pesaventob60cc122014-03-19 19:26:02 +010099 BOOST_CHECK_NE(face1, face3);
100}
101
Yukai Tu7c90e6d2015-07-11 12:21:46 +0800102BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
103{
104 EthernetFactory factory;
105
106 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
107 ndn::nfd::FACE_PERSISTENCY_PERMANENT,
108 bind([]{}),
109 bind([]{})),
110 ProtocolFactory::Error);
111
112 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
113 ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
114 bind([]{}),
115 bind([]{})),
116 ProtocolFactory::Error);
117
118 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
119 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
120 bind([]{}),
121 bind([]{})),
122 ProtocolFactory::Error);
123}
124
Davide Pesavento7726ae52014-11-23 21:01:05 +0100125BOOST_AUTO_TEST_CASE(SendPacket)
Davide Pesaventob60cc122014-03-19 19:26:02 +0100126{
Davide Pesavento7726ae52014-11-23 21:01:05 +0100127 if (m_interfaces.empty()) {
128 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
129 "cannot perform SendPacket test");
130 return;
131 }
132
Davide Pesaventob60cc122014-03-19 19:26:02 +0100133 EthernetFactory factory;
Davide Pesaventob60cc122014-03-19 19:26:02 +0100134 shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +0300135 ethernet::getDefaultMulticastAddress());
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700136
Davide Pesavento7726ae52014-11-23 21:01:05 +0100137 BOOST_REQUIRE(static_cast<bool>(face));
Davide Pesavento44deacc2014-02-19 10:48:07 +0100138 BOOST_CHECK_EQUAL(face->isLocal(), false);
Yukai Tu731f0d72015-07-04 11:14:44 +0800139 BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
Davide Pesavento94279412015-02-27 01:29:32 +0100140 BOOST_CHECK_EQUAL(face->isMultiAccess(), true);
Junxiao Shi79494162014-04-02 18:25:11 -0700141 BOOST_CHECK_EQUAL(face->getRemoteUri().toString(),
Davide Pesaventob499a602014-11-18 22:36:56 +0100142 "ether://[" + ethernet::getDefaultMulticastAddress().toString() + "]");
Junxiao Shi79494162014-04-02 18:25:11 -0700143 BOOST_CHECK_EQUAL(face->getLocalUri().toString(),
Davide Pesaventob499a602014-11-18 22:36:56 +0100144 "dev://" + m_interfaces.front().name);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100145 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 0);
146 BOOST_CHECK_EQUAL(face->getCounters().getNOutBytes(), 0);
147
Junxiao Shic099ddb2014-12-25 20:53:20 -0700148 face->onFail.connect([] (const std::string& reason) { BOOST_FAIL(reason); });
Davide Pesavento44deacc2014-02-19 10:48:07 +0100149
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +0300150 shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
151 shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
152 shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
153 shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
Davide Pesavento44deacc2014-02-19 10:48:07 +0100154
Davide Pesavento7726ae52014-11-23 21:01:05 +0100155 face->sendInterest(*interest1);
156 face->sendData (*data1 );
157 face->sendInterest(*interest2);
158 face->sendData (*data2 );
159
Matteo Sammarco66df9742014-11-21 18:31:26 +0100160 BOOST_CHECK_EQUAL(face->getCounters().getNOutBytes(),
161 14 * 4 + // 4 NDNLP headers
162 interest1->wireEncode().size() +
163 data1->wireEncode().size() +
164 interest2->wireEncode().size() +
165 data2->wireEncode().size());
Davide Pesavento44deacc2014-02-19 10:48:07 +0100166
167// m_ioRemaining = 4;
168// m_ioService.run();
169// m_ioService.reset();
170
171// BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
172// BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
173// BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
174// BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
175
176// BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
177// BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
178// BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
179// BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
180}
181
Davide Pesavento7726ae52014-11-23 21:01:05 +0100182BOOST_AUTO_TEST_CASE(ProcessIncomingPacket)
183{
184 if (m_interfaces.empty()) {
185 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
186 "cannot perform ProcessIncomingPacket test");
187 return;
188 }
189
190 EthernetFactory factory;
191 shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
192 ethernet::getDefaultMulticastAddress());
193 BOOST_REQUIRE(static_cast<bool>(face));
194
195 std::vector<Interest> recInterests;
196 std::vector<Data> recDatas;
197
Junxiao Shic099ddb2014-12-25 20:53:20 -0700198 face->onFail.connect([] (const std::string& reason) { BOOST_FAIL(reason); });
199 face->onReceiveInterest.connect(
200 [&recInterests] (const Interest& i) { recInterests.push_back(i); });
201 face->onReceiveData.connect([&recDatas] (const Data& d) { recDatas.push_back(d); });
Davide Pesavento7726ae52014-11-23 21:01:05 +0100202
203 // check that packet data is not accessed if pcap didn't capture anything (caplen == 0)
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100204 static const pcap_pkthdr zeroHeader{};
205 face->processIncomingPacket(&zeroHeader, nullptr);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100206 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 0);
207 BOOST_CHECK_EQUAL(recInterests.size(), 0);
208 BOOST_CHECK_EQUAL(recDatas.size(), 0);
209
210 // runt frame (too short)
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100211 pcap_pkthdr runtHeader{};
212 runtHeader.caplen = ethernet::HDR_LEN + 6;
Davide Pesavento7726ae52014-11-23 21:01:05 +0100213 static const uint8_t packet2[ethernet::HDR_LEN + 6]{};
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100214 face->processIncomingPacket(&runtHeader, packet2);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100215 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 0);
216 BOOST_CHECK_EQUAL(recInterests.size(), 0);
217 BOOST_CHECK_EQUAL(recDatas.size(), 0);
218
219 // valid frame, but TLV block has invalid length
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100220 pcap_pkthdr validHeader{};
221 validHeader.caplen = ethernet::HDR_LEN + ethernet::MIN_DATA_LEN;
Davide Pesavento7726ae52014-11-23 21:01:05 +0100222 static const uint8_t packet3[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100223 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100224 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
225 0x86, 0x24, // NDN ethertype
Matteo Sammarco66df9742014-11-21 18:31:26 +0100226 tlv::NdnlpData, // TLV type
227 0xfd, 0xff, 0xff // TLV length (invalid because greater than buffer size)
Davide Pesavento7726ae52014-11-23 21:01:05 +0100228 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100229 face->processIncomingPacket(&validHeader, packet3);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100230 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 0);
231 BOOST_CHECK_EQUAL(recInterests.size(), 0);
232 BOOST_CHECK_EQUAL(recDatas.size(), 0);
233
234 // valid frame, but TLV block has invalid type
Davide Pesavento7726ae52014-11-23 21:01:05 +0100235 static const uint8_t packet4[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100236 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100237 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
238 0x86, 0x24, // NDN ethertype
239 0x00, // TLV type (invalid)
240 0x00 // TLV length
241 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100242 face->processIncomingPacket(&validHeader, packet4);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100243 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 2);
244 BOOST_CHECK_EQUAL(recInterests.size(), 0);
245 BOOST_CHECK_EQUAL(recDatas.size(), 0);
246
Matteo Sammarco66df9742014-11-21 18:31:26 +0100247 // valid frame and valid NDNLP header, but invalid payload
Davide Pesavento7726ae52014-11-23 21:01:05 +0100248 static const uint8_t packet5[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100249 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100250 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
Matteo Sammarco66df9742014-11-21 18:31:26 +0100251 0x86, 0x24, // NDN ethertype
252 tlv::NdnlpData, 0x0e, // NDNLP header
253 tlv::NdnlpSequence, 0x08,
254 0, 0, 0, 0, 0, 0, 0, 0,
255 tlv::NdnlpPayload, 0x02,
256 0x00, // NDN TLV type (invalid)
257 0x00 // NDN TLV length
258 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100259 face->processIncomingPacket(&validHeader, packet5);
Matteo Sammarco66df9742014-11-21 18:31:26 +0100260 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 18);
261 BOOST_CHECK_EQUAL(recInterests.size(), 0);
262 BOOST_CHECK_EQUAL(recDatas.size(), 0);
263
264 // valid frame, valid NDNLP header, and valid NDN (interest) packet
Matteo Sammarco66df9742014-11-21 18:31:26 +0100265 static const uint8_t packet6[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
266 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
267 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
268 0x86, 0x24, // NDN ethertype
269 tlv::NdnlpData, 0x24, // NDNLP TLV type and length
270 0x51, 0x08, 0x00, 0x00, 0x00, 0x00, // rest of NDNLP header
271 0x00, 0x00, 0x00, 0x00, 0x54, 0x18,
272 tlv::Interest, 0x16, // NDN TLV type and length
Davide Pesavento7726ae52014-11-23 21:01:05 +0100273 0x07, 0x0e, 0x08, 0x07, 0x65, 0x78, // payload
274 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x08,
275 0x03, 0x66, 0x6f, 0x6f, 0x0a, 0x04,
276 0x03, 0xef, 0xe9, 0x7c
277 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100278 face->processIncomingPacket(&validHeader, packet6);
Matteo Sammarco66df9742014-11-21 18:31:26 +0100279 BOOST_CHECK_EQUAL(face->getCounters().getNInBytes(), 56);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100280 BOOST_CHECK_EQUAL(recInterests.size(), 1);
281 BOOST_CHECK_EQUAL(recDatas.size(), 0);
282}
283
Davide Pesavento44deacc2014-02-19 10:48:07 +0100284BOOST_AUTO_TEST_SUITE_END()
285
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700286} // namespace tests
Davide Pesavento44deacc2014-02-19 10:48:07 +0100287} // namespace nfd