blob: 807928774d185f13df8c44ec94abb891afb0c15e [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 Newberry73bcad32017-04-25 17:57:35 -070049 nReassembling.observe(&m_reassembler);
Eric Newberry86d31872015-09-23 16:24:59 -070050}
51
Eric Newberrya98bf932015-09-21 00:58:47 -070052void
Eric Newberry185ab292017-03-28 06:45:39 +000053GenericLinkService::setOptions(const GenericLinkService::Options& options)
54{
55 m_options = options;
56 m_fragmenter.setOptions(m_options.fragmenterOptions);
57 m_reassembler.setOptions(m_options.reassemblerOptions);
58 m_reliability.setOptions(m_options.reliabilityOptions);
59}
60
61void
62GenericLinkService::requestIdlePacket()
63{
64 // No need to request Acks to attach to this packet from LpReliability, as they are already
65 // attached in sendLpPacket
66 this->sendLpPacket({});
67}
68
69void
70GenericLinkService::sendLpPacket(lp::Packet&& pkt)
71{
72 const ssize_t mtu = this->getTransport()->getMtu();
73 if (m_options.reliabilityOptions.isEnabled) {
74 m_reliability.piggyback(pkt, mtu);
75 }
76
77 Transport::Packet tp(pkt.wireEncode());
78 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
79 ++this->nOutOverMtu;
80 NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
81 return;
82 }
83 this->sendPacket(std::move(tp));
84}
85
86void
Eric Newberrya98bf932015-09-21 00:58:47 -070087GenericLinkService::doSendInterest(const Interest& interest)
88{
89 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000090
Eric Newberryee400b52016-11-24 14:12:48 +000091 encodeLpFields(interest, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070092
Junxiao Shi0de23a22015-12-03 20:07:02 +000093 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070094}
95
96void
97GenericLinkService::doSendData(const Data& data)
98{
99 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000100
Eric Newberryee400b52016-11-24 14:12:48 +0000101 encodeLpFields(data, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700102
Junxiao Shi0de23a22015-12-03 20:07:02 +0000103 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -0700104}
105
106void
107GenericLinkService::doSendNack(const lp::Nack& nack)
108{
109 lp::Packet lpPacket(nack.getInterest().wireEncode());
110 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000111
Eric Newberryee400b52016-11-24 14:12:48 +0000112 encodeLpFields(nack, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700113
Junxiao Shi0de23a22015-12-03 20:07:02 +0000114 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -0700115}
116
Junxiao Shi0de23a22015-12-03 20:07:02 +0000117void
Eric Newberryee400b52016-11-24 14:12:48 +0000118GenericLinkService::encodeLpFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -0700119{
Eric Newberryee400b52016-11-24 14:12:48 +0000120 if (m_options.allowLocalFields) {
121 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
122 if (incomingFaceIdTag != nullptr) {
123 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
124 }
125 }
126
127 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
128 if (congestionMarkTag != nullptr) {
129 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
Eric Newberry86d31872015-09-23 16:24:59 -0700130 }
Spyridon Mastorakis9253fad2016-12-06 15:20:19 -0800131
132 shared_ptr<lp::HopCountTag> hopCountTag = netPkt.getTag<lp::HopCountTag>();
133 if (hopCountTag != nullptr) {
134 lpPacket.add<lp::HopCountTagField>(*hopCountTag);
135 }
136 else {
137 lpPacket.add<lp::HopCountTagField>(0);
138 }
Eric Newberry86d31872015-09-23 16:24:59 -0700139}
140
Eric Newberrya98bf932015-09-21 00:58:47 -0700141void
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700142GenericLinkService::sendNetPacket(lp::Packet&& pkt)
143{
144 std::vector<lp::Packet> frags;
Eric Newberry7b0071e2017-07-03 17:33:31 +0000145 ssize_t mtu = this->getTransport()->getMtu();
146
147 // Make space for feature fields in fragments
148 if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
149 mtu -= LpReliability::RESERVED_HEADER_SPACE;
150 BOOST_ASSERT(mtu > 0);
151 }
152
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700153 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
154 bool isOk = false;
155 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
156 if (!isOk) {
157 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000158 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700159 return;
160 }
161 }
162 else {
Eric Newberry185ab292017-03-28 06:45:39 +0000163 frags.push_back(std::move(pkt));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700164 }
165
Eric Newberry185ab292017-03-28 06:45:39 +0000166 if (frags.size() == 1) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700167 // even if indexed fragmentation is enabled, the fragmenter should not
168 // fragment the packet if it can fit in MTU
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700169 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
170 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
171 }
172
Eric Newberry7b0071e2017-07-03 17:33:31 +0000173 // Only assign sequences to fragments if packet contains more than 1 fragment
174 if (frags.size() > 1) {
Eric Newberry185ab292017-03-28 06:45:39 +0000175 // Assign sequences to all fragments
176 this->assignSequences(frags);
177 }
178
179 if (m_options.reliabilityOptions.isEnabled && frags.front().has<lp::FragmentField>()) {
Eric Newberry7b0071e2017-07-03 17:33:31 +0000180 m_reliability.handleOutgoing(frags);
Eric Newberry185ab292017-03-28 06:45:39 +0000181 }
182
183 for (lp::Packet& frag : frags) {
184 this->sendLpPacket(std::move(frag));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700185 }
186}
187
188void
189GenericLinkService::assignSequence(lp::Packet& pkt)
190{
191 pkt.set<lp::SequenceField>(++m_lastSeqNo);
192}
193
194void
195GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
196{
197 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
198}
199
200void
Eric Newberrya98bf932015-09-21 00:58:47 -0700201GenericLinkService::doReceivePacket(Transport::Packet&& packet)
202{
Eric Newberry86d31872015-09-23 16:24:59 -0700203 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700204 lp::Packet pkt(packet.packet);
205
Eric Newberry185ab292017-03-28 06:45:39 +0000206 if (m_options.reliabilityOptions.isEnabled) {
207 m_reliability.processIncomingPacket(pkt);
208 }
209
Eric Newberrya1939ba2015-10-09 12:35:03 -0700210 if (!pkt.has<lp::FragmentField>()) {
211 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
212 return;
213 }
214
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700215 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
216 !m_options.allowReassembly) {
217 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700218 return;
219 }
220
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700221 bool isReassembled = false;
222 Block netPkt;
223 lp::Packet firstPkt;
224 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
225 pkt);
226 if (isReassembled) {
227 this->decodeNetPacket(netPkt, firstPkt);
228 }
229 }
230 catch (const tlv::Error& e) {
231 ++this->nInLpInvalid;
232 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
233 }
234}
Eric Newberry86d31872015-09-23 16:24:59 -0700235
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700236void
237GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
238{
239 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700240 switch (netPkt.type()) {
241 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700242 if (firstPkt.has<lp::NackField>()) {
243 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700244 }
245 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700246 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700247 }
248 break;
249 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700250 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700251 break;
252 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700253 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700254 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
255 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700256 }
257 }
Eric Newberry86d31872015-09-23 16:24:59 -0700258 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700259 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700260 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
261 }
262}
263
Eric Newberry86d31872015-09-23 16:24:59 -0700264void
265GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
266{
267 BOOST_ASSERT(netPkt.type() == tlv::Interest);
268 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
269
270 // forwarding expects Interest to be created with make_shared
271 auto interest = make_shared<Interest>(netPkt);
272
Spyridon Mastorakis9253fad2016-12-06 15:20:19 -0800273 // Increment HopCount
274 if (firstPkt.has<lp::HopCountTagField>()) {
275 interest->setTag(make_shared<lp::HopCountTag>(firstPkt.get<lp::HopCountTagField>() + 1));
276 }
277
Eric Newberry86d31872015-09-23 16:24:59 -0700278 if (firstPkt.has<lp::NextHopFaceIdField>()) {
279 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000280 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700281 }
282 else {
283 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
284 return;
285 }
286 }
287
288 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700289 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700290 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
291 return;
292 }
293
294 if (firstPkt.has<lp::IncomingFaceIdField>()) {
295 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
296 }
297
Eric Newberryee400b52016-11-24 14:12:48 +0000298 if (firstPkt.has<lp::CongestionMarkField>()) {
299 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
300 }
301
Eric Newberry86d31872015-09-23 16:24:59 -0700302 this->receiveInterest(*interest);
303}
304
305void
306GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
307{
308 BOOST_ASSERT(netPkt.type() == tlv::Data);
309
310 // forwarding expects Data to be created with make_shared
311 auto data = make_shared<Data>(netPkt);
312
Spyridon Mastorakis9253fad2016-12-06 15:20:19 -0800313 if (firstPkt.has<lp::HopCountTagField>()) {
314 data->setTag(make_shared<lp::HopCountTag>(firstPkt.get<lp::HopCountTagField>() + 1));
315 }
316
Eric Newberry86d31872015-09-23 16:24:59 -0700317 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700318 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700319 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
320 return;
321 }
322
323 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700324 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700325 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
326 return;
327 }
328
329 if (firstPkt.has<lp::CachePolicyField>()) {
Junxiao Shi6eb02712017-05-27 22:48:02 +0000330 // CachePolicy is unprivileged and does not require allowLocalFields option.
331 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
332 // so it's unnecessary to check here.
333 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700334 }
335
336 if (firstPkt.has<lp::IncomingFaceIdField>()) {
337 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
338 }
339
Eric Newberryee400b52016-11-24 14:12:48 +0000340 if (firstPkt.has<lp::CongestionMarkField>()) {
341 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
342 }
343
Eric Newberry86d31872015-09-23 16:24:59 -0700344 this->receiveData(*data);
345}
346
347void
348GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
349{
350 BOOST_ASSERT(netPkt.type() == tlv::Interest);
351 BOOST_ASSERT(firstPkt.has<lp::NackField>());
352
353 lp::Nack nack((Interest(netPkt)));
354 nack.setHeader(firstPkt.get<lp::NackField>());
355
356 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700357 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700358 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
359 return;
360 }
361
362 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700363 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700364 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
365 return;
366 }
367
368 if (firstPkt.has<lp::IncomingFaceIdField>()) {
369 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
370 }
371
Eric Newberryee400b52016-11-24 14:12:48 +0000372 if (firstPkt.has<lp::CongestionMarkField>()) {
373 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
374 }
375
Eric Newberry86d31872015-09-23 16:24:59 -0700376 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700377}
378
379} // namespace face
380} // namespace nfd