blob: bbd8e03f1765cc4f0deb8a31423077cdd7dbba69 [file] [log] [blame]
Eric Newberrya98bf932015-09-21 00:58:47 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Eric Newberry7b0071e2017-07-03 17:33:31 +00002/*
Eric Newberry185ab292017-03-28 06:45:39 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Eric Newberrya98bf932015-09-21 00:58:47 -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 "generic-link-service.hpp"
Junxiao Shicbc8e942016-09-06 03:17:45 +000027#include <ndn-cxx/lp/tags.hpp>
Eric Newberrya98bf932015-09-21 00:58:47 -070028
29namespace nfd {
30namespace face {
31
32NFD_LOG_INIT("GenericLinkService");
33
Eric Newberry86d31872015-09-23 16:24:59 -070034GenericLinkService::Options::Options()
35 : allowLocalFields(false)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070036 , allowFragmentation(false)
37 , allowReassembly(false)
Eric Newberry86d31872015-09-23 16:24:59 -070038{
39}
40
41GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
Eric Newberry73bcad32017-04-25 17:57:35 -070042 : m_options(options)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070043 , m_fragmenter(m_options.fragmenterOptions, this)
44 , m_reassembler(m_options.reassemblerOptions, this)
Eric Newberry185ab292017-03-28 06:45:39 +000045 , m_reliability(m_options.reliabilityOptions, this)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070046 , m_lastSeqNo(-2)
Eric Newberry86d31872015-09-23 16:24:59 -070047{
Junxiao Shi0de23a22015-12-03 20:07:02 +000048 m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
Eric Newberry41aba102017-11-01 16:42:13 -070049 m_reliability.onDroppedInterest.connect([this] (const Interest& i) { this->notifyDroppedInterest(i); });
Eric Newberry73bcad32017-04-25 17:57:35 -070050 nReassembling.observe(&m_reassembler);
Eric Newberry86d31872015-09-23 16:24:59 -070051}
52
Eric Newberrya98bf932015-09-21 00:58:47 -070053void
Eric Newberry185ab292017-03-28 06:45:39 +000054GenericLinkService::setOptions(const GenericLinkService::Options& options)
55{
56 m_options = options;
57 m_fragmenter.setOptions(m_options.fragmenterOptions);
58 m_reassembler.setOptions(m_options.reassemblerOptions);
59 m_reliability.setOptions(m_options.reliabilityOptions);
60}
61
62void
63GenericLinkService::requestIdlePacket()
64{
65 // No need to request Acks to attach to this packet from LpReliability, as they are already
66 // attached in sendLpPacket
67 this->sendLpPacket({});
68}
69
70void
71GenericLinkService::sendLpPacket(lp::Packet&& pkt)
72{
73 const ssize_t mtu = this->getTransport()->getMtu();
74 if (m_options.reliabilityOptions.isEnabled) {
75 m_reliability.piggyback(pkt, mtu);
76 }
77
78 Transport::Packet tp(pkt.wireEncode());
79 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
80 ++this->nOutOverMtu;
81 NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
82 return;
83 }
84 this->sendPacket(std::move(tp));
85}
86
87void
Eric Newberrya98bf932015-09-21 00:58:47 -070088GenericLinkService::doSendInterest(const Interest& interest)
89{
90 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000091
Eric Newberryee400b52016-11-24 14:12:48 +000092 encodeLpFields(interest, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070093
Eric Newberry41aba102017-11-01 16:42:13 -070094 this->sendNetPacket(std::move(lpPacket), true);
Eric Newberrya98bf932015-09-21 00:58:47 -070095}
96
97void
98GenericLinkService::doSendData(const Data& data)
99{
100 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000101
Eric Newberryee400b52016-11-24 14:12:48 +0000102 encodeLpFields(data, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700103
Eric Newberry41aba102017-11-01 16:42:13 -0700104 this->sendNetPacket(std::move(lpPacket), false);
Eric Newberrya98bf932015-09-21 00:58:47 -0700105}
106
107void
108GenericLinkService::doSendNack(const lp::Nack& nack)
109{
110 lp::Packet lpPacket(nack.getInterest().wireEncode());
111 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000112
Eric Newberryee400b52016-11-24 14:12:48 +0000113 encodeLpFields(nack, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700114
Eric Newberry41aba102017-11-01 16:42:13 -0700115 this->sendNetPacket(std::move(lpPacket), false);
Eric Newberrya98bf932015-09-21 00:58:47 -0700116}
117
Junxiao Shi0de23a22015-12-03 20:07:02 +0000118void
Eric Newberry41aba102017-11-01 16:42:13 -0700119GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -0700120{
Eric Newberryee400b52016-11-24 14:12:48 +0000121 if (m_options.allowLocalFields) {
122 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
123 if (incomingFaceIdTag != nullptr) {
124 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
125 }
126 }
127
128 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
129 if (congestionMarkTag != nullptr) {
130 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
Eric Newberry86d31872015-09-23 16:24:59 -0700131 }
Eric Newberry86d31872015-09-23 16:24:59 -0700132}
133
Eric Newberrya98bf932015-09-21 00:58:47 -0700134void
Eric Newberry41aba102017-11-01 16:42:13 -0700135GenericLinkService::sendNetPacket(lp::Packet&& pkt, bool isInterest)
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700136{
137 std::vector<lp::Packet> frags;
Eric Newberry7b0071e2017-07-03 17:33:31 +0000138 ssize_t mtu = this->getTransport()->getMtu();
139
140 // Make space for feature fields in fragments
141 if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
142 mtu -= LpReliability::RESERVED_HEADER_SPACE;
143 BOOST_ASSERT(mtu > 0);
144 }
145
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700146 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
147 bool isOk = false;
148 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
149 if (!isOk) {
150 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000151 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700152 return;
153 }
154 }
155 else {
Eric Newberry41aba102017-11-01 16:42:13 -0700156 if (m_options.reliabilityOptions.isEnabled) {
157 frags.push_back(pkt);
158 }
159 else {
160 frags.push_back(std::move(pkt));
161 }
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700162 }
163
Eric Newberry185ab292017-03-28 06:45:39 +0000164 if (frags.size() == 1) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700165 // even if indexed fragmentation is enabled, the fragmenter should not
166 // fragment the packet if it can fit in MTU
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700167 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
168 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
169 }
170
Eric Newberry7b0071e2017-07-03 17:33:31 +0000171 // Only assign sequences to fragments if packet contains more than 1 fragment
172 if (frags.size() > 1) {
Eric Newberry185ab292017-03-28 06:45:39 +0000173 // Assign sequences to all fragments
174 this->assignSequences(frags);
175 }
176
177 if (m_options.reliabilityOptions.isEnabled && frags.front().has<lp::FragmentField>()) {
Eric Newberry41aba102017-11-01 16:42:13 -0700178 m_reliability.handleOutgoing(frags, std::move(pkt), isInterest);
Eric Newberry185ab292017-03-28 06:45:39 +0000179 }
180
181 for (lp::Packet& frag : frags) {
182 this->sendLpPacket(std::move(frag));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700183 }
184}
185
186void
187GenericLinkService::assignSequence(lp::Packet& pkt)
188{
189 pkt.set<lp::SequenceField>(++m_lastSeqNo);
190}
191
192void
193GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
194{
195 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
196}
197
198void
Eric Newberrya98bf932015-09-21 00:58:47 -0700199GenericLinkService::doReceivePacket(Transport::Packet&& packet)
200{
Eric Newberry86d31872015-09-23 16:24:59 -0700201 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700202 lp::Packet pkt(packet.packet);
203
Eric Newberry185ab292017-03-28 06:45:39 +0000204 if (m_options.reliabilityOptions.isEnabled) {
205 m_reliability.processIncomingPacket(pkt);
206 }
207
Eric Newberrya1939ba2015-10-09 12:35:03 -0700208 if (!pkt.has<lp::FragmentField>()) {
209 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
210 return;
211 }
212
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700213 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
214 !m_options.allowReassembly) {
215 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700216 return;
217 }
218
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700219 bool isReassembled = false;
220 Block netPkt;
221 lp::Packet firstPkt;
222 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
223 pkt);
224 if (isReassembled) {
225 this->decodeNetPacket(netPkt, firstPkt);
226 }
227 }
228 catch (const tlv::Error& e) {
229 ++this->nInLpInvalid;
230 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
231 }
232}
Eric Newberry86d31872015-09-23 16:24:59 -0700233
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700234void
235GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
236{
237 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700238 switch (netPkt.type()) {
239 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700240 if (firstPkt.has<lp::NackField>()) {
241 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700242 }
243 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700244 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700245 }
246 break;
247 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700248 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700249 break;
250 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700251 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700252 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
253 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700254 }
255 }
Eric Newberry86d31872015-09-23 16:24:59 -0700256 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700257 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700258 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
259 }
260}
261
Eric Newberry86d31872015-09-23 16:24:59 -0700262void
263GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
264{
265 BOOST_ASSERT(netPkt.type() == tlv::Interest);
266 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
267
268 // forwarding expects Interest to be created with make_shared
269 auto interest = make_shared<Interest>(netPkt);
270
271 if (firstPkt.has<lp::NextHopFaceIdField>()) {
272 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000273 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700274 }
275 else {
276 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
277 return;
278 }
279 }
280
281 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700282 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700283 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
284 return;
285 }
286
287 if (firstPkt.has<lp::IncomingFaceIdField>()) {
288 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
289 }
290
Eric Newberryee400b52016-11-24 14:12:48 +0000291 if (firstPkt.has<lp::CongestionMarkField>()) {
292 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
293 }
294
Eric Newberry86d31872015-09-23 16:24:59 -0700295 this->receiveInterest(*interest);
296}
297
298void
299GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
300{
301 BOOST_ASSERT(netPkt.type() == tlv::Data);
302
303 // forwarding expects Data to be created with make_shared
304 auto data = make_shared<Data>(netPkt);
305
306 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700307 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700308 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
309 return;
310 }
311
312 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700313 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700314 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
315 return;
316 }
317
318 if (firstPkt.has<lp::CachePolicyField>()) {
Junxiao Shi6eb02712017-05-27 22:48:02 +0000319 // CachePolicy is unprivileged and does not require allowLocalFields option.
320 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
321 // so it's unnecessary to check here.
322 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700323 }
324
325 if (firstPkt.has<lp::IncomingFaceIdField>()) {
326 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
327 }
328
Eric Newberryee400b52016-11-24 14:12:48 +0000329 if (firstPkt.has<lp::CongestionMarkField>()) {
330 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
331 }
332
Eric Newberry86d31872015-09-23 16:24:59 -0700333 this->receiveData(*data);
334}
335
336void
337GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
338{
339 BOOST_ASSERT(netPkt.type() == tlv::Interest);
340 BOOST_ASSERT(firstPkt.has<lp::NackField>());
341
342 lp::Nack nack((Interest(netPkt)));
343 nack.setHeader(firstPkt.get<lp::NackField>());
344
345 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700346 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700347 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
348 return;
349 }
350
351 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700352 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700353 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
354 return;
355 }
356
357 if (firstPkt.has<lp::IncomingFaceIdField>()) {
358 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
359 }
360
Eric Newberryee400b52016-11-24 14:12:48 +0000361 if (firstPkt.has<lp::CongestionMarkField>()) {
362 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
363 }
364
Eric Newberry86d31872015-09-23 16:24:59 -0700365 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700366}
367
368} // namespace face
369} // namespace nfd