blob: 7d97016a5a44f4d35b79002e244c41e6966d103c [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
Junxiao Shida93f1f2015-11-11 06:13:16 -070037BOOST_AUTO_TEST_SUITE(Face)
38
39using nfd::Face;
40
Davide Pesaventob60cc122014-03-19 19:26:02 +010041class InterfacesFixture : protected BaseFixture
42{
43protected:
44 InterfacesFixture()
45 {
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +030046 EthernetFactory factory;
47
Davide Pesaventob499a602014-11-18 22:36:56 +010048 for (const auto& netif : listNetworkInterfaces()) {
49 if (!netif.isLoopback() && netif.isUp()) {
50 try {
51 factory.createMulticastFace(netif, ethernet::getBroadcastAddress());
52 }
53 catch (Face::Error&) {
54 continue;
55 }
Davide Pesaventob60cc122014-03-19 19:26:02 +010056
Davide Pesaventob499a602014-11-18 22:36:56 +010057 m_interfaces.push_back(netif);
Davide Pesaventob60cc122014-03-19 19:26:02 +010058 }
Davide Pesaventob499a602014-11-18 22:36:56 +010059 }
Davide Pesaventob60cc122014-03-19 19:26:02 +010060 }
61
62protected:
Davide Pesaventob499a602014-11-18 22:36:56 +010063 std::vector<NetworkInterfaceInfo> m_interfaces;
Davide Pesaventob60cc122014-03-19 19:26:02 +010064};
65
Junxiao Shida93f1f2015-11-11 06:13:16 -070066BOOST_FIXTURE_TEST_SUITE(TestEthernet, InterfacesFixture)
Davide Pesaventob60cc122014-03-19 19:26:02 +010067
Davide Pesavento7726ae52014-11-23 21:01:05 +010068BOOST_AUTO_TEST_CASE(GetChannels)
Davide Pesavento44deacc2014-02-19 10:48:07 +010069{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080070 EthernetFactory factory;
Davide Pesavento44deacc2014-02-19 10:48:07 +010071
Davide Pesavento7726ae52014-11-23 21:01:05 +010072 auto channels = factory.getChannels();
73 BOOST_CHECK_EQUAL(channels.empty(), true);
74}
Davide Pesavento44deacc2014-02-19 10:48:07 +010075
Davide Pesavento7726ae52014-11-23 21:01:05 +010076BOOST_AUTO_TEST_CASE(MulticastFacesMap)
77{
78 if (m_interfaces.empty()) {
79 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
80 "cannot perform MulticastFacesMap test");
81 return;
82 }
83
84 EthernetFactory factory;
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +030085 shared_ptr<EthernetFace> face1 = factory.createMulticastFace(m_interfaces.front(),
86 ethernet::getBroadcastAddress());
87 shared_ptr<EthernetFace> face1bis = factory.createMulticastFace(m_interfaces.front(),
88 ethernet::getBroadcastAddress());
Davide Pesaventob60cc122014-03-19 19:26:02 +010089 BOOST_CHECK_EQUAL(face1, face1bis);
90
Davide Pesaventob499a602014-11-18 22:36:56 +010091 if (m_interfaces.size() > 1) {
92 shared_ptr<EthernetFace> face2 = factory.createMulticastFace(m_interfaces.back(),
93 ethernet::getBroadcastAddress());
94 BOOST_CHECK_NE(face1, face2);
95 }
96 else {
Davide Pesavento7726ae52014-11-23 21:01:05 +010097 BOOST_WARN_MESSAGE(false, "Only one interface available for pcap, "
98 "cannot test second EthernetFace creation");
Davide Pesaventob499a602014-11-18 22:36:56 +010099 }
Davide Pesaventob60cc122014-03-19 19:26:02 +0100100
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +0300101 shared_ptr<EthernetFace> face3 = factory.createMulticastFace(m_interfaces.front(),
102 ethernet::getDefaultMulticastAddress());
Davide Pesaventob60cc122014-03-19 19:26:02 +0100103 BOOST_CHECK_NE(face1, face3);
104}
105
Yukai Tu7c90e6d2015-07-11 12:21:46 +0800106BOOST_AUTO_TEST_CASE(UnsupportedFaceCreate)
107{
108 EthernetFactory factory;
109
110 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
111 ndn::nfd::FACE_PERSISTENCY_PERMANENT,
112 bind([]{}),
113 bind([]{})),
114 ProtocolFactory::Error);
115
116 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
117 ndn::nfd::FACE_PERSISTENCY_ON_DEMAND,
118 bind([]{}),
119 bind([]{})),
120 ProtocolFactory::Error);
121
122 BOOST_CHECK_THROW(factory.createFace(FaceUri("ether://[08:00:27:01:01:01]"),
123 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
124 bind([]{}),
125 bind([]{})),
126 ProtocolFactory::Error);
127}
128
Davide Pesavento7726ae52014-11-23 21:01:05 +0100129BOOST_AUTO_TEST_CASE(SendPacket)
Davide Pesaventob60cc122014-03-19 19:26:02 +0100130{
Davide Pesavento7726ae52014-11-23 21:01:05 +0100131 if (m_interfaces.empty()) {
132 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
133 "cannot perform SendPacket test");
134 return;
135 }
136
Davide Pesaventob60cc122014-03-19 19:26:02 +0100137 EthernetFactory factory;
Davide Pesaventob60cc122014-03-19 19:26:02 +0100138 shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +0300139 ethernet::getDefaultMulticastAddress());
Alexander Afanasyev355c0662014-03-20 18:08:17 -0700140
Davide Pesavento7726ae52014-11-23 21:01:05 +0100141 BOOST_REQUIRE(static_cast<bool>(face));
Davide Pesavento44deacc2014-02-19 10:48:07 +0100142 BOOST_CHECK_EQUAL(face->isLocal(), false);
Yukai Tu731f0d72015-07-04 11:14:44 +0800143 BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
Davide Pesavento94279412015-02-27 01:29:32 +0100144 BOOST_CHECK_EQUAL(face->isMultiAccess(), true);
Junxiao Shi79494162014-04-02 18:25:11 -0700145 BOOST_CHECK_EQUAL(face->getRemoteUri().toString(),
Davide Pesaventob499a602014-11-18 22:36:56 +0100146 "ether://[" + ethernet::getDefaultMulticastAddress().toString() + "]");
Junxiao Shi79494162014-04-02 18:25:11 -0700147 BOOST_CHECK_EQUAL(face->getLocalUri().toString(),
Davide Pesaventob499a602014-11-18 22:36:56 +0100148 "dev://" + m_interfaces.front().name);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700149 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
150 BOOST_CHECK_EQUAL(face->getCounters().nOutBytes, 0);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100151
Junxiao Shic099ddb2014-12-25 20:53:20 -0700152 face->onFail.connect([] (const std::string& reason) { BOOST_FAIL(reason); });
Davide Pesavento44deacc2014-02-19 10:48:07 +0100153
Alexander Afanasyevb56c5b92014-06-05 08:05:24 +0300154 shared_ptr<Interest> interest1 = makeInterest("ndn:/TpnzGvW9R");
155 shared_ptr<Data> data1 = makeData("ndn:/KfczhUqVix");
156 shared_ptr<Interest> interest2 = makeInterest("ndn:/QWiIMfj5sL");
157 shared_ptr<Data> data2 = makeData("ndn:/XNBV796f");
Davide Pesavento44deacc2014-02-19 10:48:07 +0100158
Davide Pesavento7726ae52014-11-23 21:01:05 +0100159 face->sendInterest(*interest1);
160 face->sendData (*data1 );
161 face->sendInterest(*interest2);
162 face->sendData (*data2 );
163
Junxiao Shida93f1f2015-11-11 06:13:16 -0700164 BOOST_CHECK_EQUAL(face->getCounters().nOutBytes,
Matteo Sammarco66df9742014-11-21 18:31:26 +0100165 14 * 4 + // 4 NDNLP headers
166 interest1->wireEncode().size() +
167 data1->wireEncode().size() +
168 interest2->wireEncode().size() +
169 data2->wireEncode().size());
Davide Pesavento44deacc2014-02-19 10:48:07 +0100170
171// m_ioRemaining = 4;
172// m_ioService.run();
173// m_ioService.reset();
174
175// BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
176// BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
177// BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
178// BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
179
180// BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
181// BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
182// BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
183// BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
184}
185
Davide Pesavento7726ae52014-11-23 21:01:05 +0100186BOOST_AUTO_TEST_CASE(ProcessIncomingPacket)
187{
188 if (m_interfaces.empty()) {
189 BOOST_WARN_MESSAGE(false, "No interfaces available for pcap, "
190 "cannot perform ProcessIncomingPacket test");
191 return;
192 }
193
194 EthernetFactory factory;
195 shared_ptr<EthernetFace> face = factory.createMulticastFace(m_interfaces.front(),
196 ethernet::getDefaultMulticastAddress());
197 BOOST_REQUIRE(static_cast<bool>(face));
198
199 std::vector<Interest> recInterests;
200 std::vector<Data> recDatas;
201
Junxiao Shic099ddb2014-12-25 20:53:20 -0700202 face->onFail.connect([] (const std::string& reason) { BOOST_FAIL(reason); });
203 face->onReceiveInterest.connect(
204 [&recInterests] (const Interest& i) { recInterests.push_back(i); });
205 face->onReceiveData.connect([&recDatas] (const Data& d) { recDatas.push_back(d); });
Davide Pesavento7726ae52014-11-23 21:01:05 +0100206
207 // check that packet data is not accessed if pcap didn't capture anything (caplen == 0)
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100208 static const pcap_pkthdr zeroHeader{};
209 face->processIncomingPacket(&zeroHeader, nullptr);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700210 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100211 BOOST_CHECK_EQUAL(recInterests.size(), 0);
212 BOOST_CHECK_EQUAL(recDatas.size(), 0);
213
214 // runt frame (too short)
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100215 pcap_pkthdr runtHeader{};
216 runtHeader.caplen = ethernet::HDR_LEN + 6;
Davide Pesavento7726ae52014-11-23 21:01:05 +0100217 static const uint8_t packet2[ethernet::HDR_LEN + 6]{};
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100218 face->processIncomingPacket(&runtHeader, packet2);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700219 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100220 BOOST_CHECK_EQUAL(recInterests.size(), 0);
221 BOOST_CHECK_EQUAL(recDatas.size(), 0);
222
223 // valid frame, but TLV block has invalid length
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100224 pcap_pkthdr validHeader{};
225 validHeader.caplen = ethernet::HDR_LEN + ethernet::MIN_DATA_LEN;
Davide Pesavento7726ae52014-11-23 21:01:05 +0100226 static const uint8_t packet3[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100227 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100228 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
229 0x86, 0x24, // NDN ethertype
Matteo Sammarco66df9742014-11-21 18:31:26 +0100230 tlv::NdnlpData, // TLV type
231 0xfd, 0xff, 0xff // TLV length (invalid because greater than buffer size)
Davide Pesavento7726ae52014-11-23 21:01:05 +0100232 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100233 face->processIncomingPacket(&validHeader, packet3);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700234 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 0);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100235 BOOST_CHECK_EQUAL(recInterests.size(), 0);
236 BOOST_CHECK_EQUAL(recDatas.size(), 0);
237
238 // valid frame, but TLV block has invalid type
Davide Pesavento7726ae52014-11-23 21:01:05 +0100239 static const uint8_t packet4[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100240 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100241 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
242 0x86, 0x24, // NDN ethertype
243 0x00, // TLV type (invalid)
244 0x00 // TLV length
245 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100246 face->processIncomingPacket(&validHeader, packet4);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700247 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 2);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100248 BOOST_CHECK_EQUAL(recInterests.size(), 0);
249 BOOST_CHECK_EQUAL(recDatas.size(), 0);
250
Matteo Sammarco66df9742014-11-21 18:31:26 +0100251 // valid frame and valid NDNLP header, but invalid payload
Davide Pesavento7726ae52014-11-23 21:01:05 +0100252 static const uint8_t packet5[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
Matteo Sammarco66df9742014-11-21 18:31:26 +0100253 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
Davide Pesavento7726ae52014-11-23 21:01:05 +0100254 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
Matteo Sammarco66df9742014-11-21 18:31:26 +0100255 0x86, 0x24, // NDN ethertype
256 tlv::NdnlpData, 0x0e, // NDNLP header
257 tlv::NdnlpSequence, 0x08,
258 0, 0, 0, 0, 0, 0, 0, 0,
259 tlv::NdnlpPayload, 0x02,
260 0x00, // NDN TLV type (invalid)
261 0x00 // NDN TLV length
262 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100263 face->processIncomingPacket(&validHeader, packet5);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700264 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 18);
Matteo Sammarco66df9742014-11-21 18:31:26 +0100265 BOOST_CHECK_EQUAL(recInterests.size(), 0);
266 BOOST_CHECK_EQUAL(recDatas.size(), 0);
267
268 // valid frame, valid NDNLP header, and valid NDN (interest) packet
Matteo Sammarco66df9742014-11-21 18:31:26 +0100269 static const uint8_t packet6[ethernet::HDR_LEN + ethernet::MIN_DATA_LEN]{
270 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, // destination address
271 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, // source address
272 0x86, 0x24, // NDN ethertype
273 tlv::NdnlpData, 0x24, // NDNLP TLV type and length
274 0x51, 0x08, 0x00, 0x00, 0x00, 0x00, // rest of NDNLP header
275 0x00, 0x00, 0x00, 0x00, 0x54, 0x18,
276 tlv::Interest, 0x16, // NDN TLV type and length
Davide Pesavento7726ae52014-11-23 21:01:05 +0100277 0x07, 0x0e, 0x08, 0x07, 0x65, 0x78, // payload
278 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x08,
279 0x03, 0x66, 0x6f, 0x6f, 0x0a, 0x04,
280 0x03, 0xef, 0xe9, 0x7c
281 };
Davide Pesaventoed89ccc2015-11-01 20:35:04 +0100282 face->processIncomingPacket(&validHeader, packet6);
Junxiao Shida93f1f2015-11-11 06:13:16 -0700283 BOOST_CHECK_EQUAL(face->getCounters().nInBytes, 56);
Davide Pesavento7726ae52014-11-23 21:01:05 +0100284 BOOST_CHECK_EQUAL(recInterests.size(), 1);
285 BOOST_CHECK_EQUAL(recDatas.size(), 0);
286}
287
Junxiao Shida93f1f2015-11-11 06:13:16 -0700288BOOST_AUTO_TEST_SUITE_END() // TestEthernet
289BOOST_AUTO_TEST_SUITE_END() // Face
Davide Pesavento44deacc2014-02-19 10:48:07 +0100290
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700291} // namespace tests
Davide Pesavento44deacc2014-02-19 10:48:07 +0100292} // namespace nfd