blob: 9d1d0fc2775bdb55248349c230773d89db0f6145 [file] [log] [blame]
Eric Newberrya98bf932015-09-21 00:58:47 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
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 Newberry4c3e6b82015-11-10 16:48:42 -070034GenericLinkServiceCounters::GenericLinkServiceCounters(const LpReassembler& reassembler)
35 : nReassembling(reassembler)
36{
37}
38
Eric Newberry86d31872015-09-23 16:24:59 -070039GenericLinkService::Options::Options()
40 : allowLocalFields(false)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070041 , allowFragmentation(false)
42 , allowReassembly(false)
Eric Newberry86d31872015-09-23 16:24:59 -070043{
44}
45
46GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070047 : GenericLinkServiceCounters(m_reassembler)
48 , m_options(options)
49 , m_fragmenter(m_options.fragmenterOptions, this)
50 , m_reassembler(m_options.reassemblerOptions, this)
Eric Newberry185ab292017-03-28 06:45:39 +000051 , m_reliability(m_options.reliabilityOptions, this)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070052 , m_lastSeqNo(-2)
Eric Newberry86d31872015-09-23 16:24:59 -070053{
Junxiao Shi0de23a22015-12-03 20:07:02 +000054 m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
Eric Newberry86d31872015-09-23 16:24:59 -070055}
56
Eric Newberrya98bf932015-09-21 00:58:47 -070057void
Eric Newberry185ab292017-03-28 06:45:39 +000058GenericLinkService::setOptions(const GenericLinkService::Options& options)
59{
60 m_options = options;
61 m_fragmenter.setOptions(m_options.fragmenterOptions);
62 m_reassembler.setOptions(m_options.reassemblerOptions);
63 m_reliability.setOptions(m_options.reliabilityOptions);
64}
65
66void
67GenericLinkService::requestIdlePacket()
68{
69 // No need to request Acks to attach to this packet from LpReliability, as they are already
70 // attached in sendLpPacket
71 this->sendLpPacket({});
72}
73
74void
75GenericLinkService::sendLpPacket(lp::Packet&& pkt)
76{
77 const ssize_t mtu = this->getTransport()->getMtu();
78 if (m_options.reliabilityOptions.isEnabled) {
79 m_reliability.piggyback(pkt, mtu);
80 }
81
82 Transport::Packet tp(pkt.wireEncode());
83 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
84 ++this->nOutOverMtu;
85 NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
86 return;
87 }
88 this->sendPacket(std::move(tp));
89}
90
91void
Eric Newberrya98bf932015-09-21 00:58:47 -070092GenericLinkService::doSendInterest(const Interest& interest)
93{
94 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000095
Eric Newberryee400b52016-11-24 14:12:48 +000096 encodeLpFields(interest, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070097
Junxiao Shi0de23a22015-12-03 20:07:02 +000098 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070099}
100
101void
102GenericLinkService::doSendData(const Data& data)
103{
104 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000105
Eric Newberryee400b52016-11-24 14:12:48 +0000106 encodeLpFields(data, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700107
Junxiao Shi0de23a22015-12-03 20:07:02 +0000108 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -0700109}
110
111void
112GenericLinkService::doSendNack(const lp::Nack& nack)
113{
114 lp::Packet lpPacket(nack.getInterest().wireEncode());
115 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000116
Eric Newberryee400b52016-11-24 14:12:48 +0000117 encodeLpFields(nack, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700118
Junxiao Shi0de23a22015-12-03 20:07:02 +0000119 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -0700120}
121
Junxiao Shi0de23a22015-12-03 20:07:02 +0000122void
Eric Newberryee400b52016-11-24 14:12:48 +0000123GenericLinkService::encodeLpFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -0700124{
Eric Newberryee400b52016-11-24 14:12:48 +0000125 if (m_options.allowLocalFields) {
126 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
127 if (incomingFaceIdTag != nullptr) {
128 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
129 }
130 }
131
132 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
133 if (congestionMarkTag != nullptr) {
134 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
Eric Newberry86d31872015-09-23 16:24:59 -0700135 }
Eric Newberry86d31872015-09-23 16:24:59 -0700136}
137
Eric Newberrya98bf932015-09-21 00:58:47 -0700138void
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700139GenericLinkService::sendNetPacket(lp::Packet&& pkt)
140{
141 std::vector<lp::Packet> frags;
142 const ssize_t mtu = this->getTransport()->getMtu();
143 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
144 bool isOk = false;
145 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
146 if (!isOk) {
147 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000148 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700149 return;
150 }
151 }
152 else {
Eric Newberry185ab292017-03-28 06:45:39 +0000153 frags.push_back(std::move(pkt));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700154 }
155
Eric Newberry185ab292017-03-28 06:45:39 +0000156 if (frags.size() == 1) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700157 // even if indexed fragmentation is enabled, the fragmenter should not
158 // fragment the packet if it can fit in MTU
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700159 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
160 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
161 }
162
Eric Newberry185ab292017-03-28 06:45:39 +0000163 // Only assign sequences to fragments if reliability enabled and packet contains a fragment,
164 // or there is more than 1 fragment
165 if ((m_options.reliabilityOptions.isEnabled && frags.front().has<lp::FragmentField>()) ||
166 frags.size() > 1) {
167 // Assign sequences to all fragments
168 this->assignSequences(frags);
169 }
170
171 if (m_options.reliabilityOptions.isEnabled && frags.front().has<lp::FragmentField>()) {
172 m_reliability.observeOutgoing(frags);
173 }
174
175 for (lp::Packet& frag : frags) {
176 this->sendLpPacket(std::move(frag));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700177 }
178}
179
180void
181GenericLinkService::assignSequence(lp::Packet& pkt)
182{
183 pkt.set<lp::SequenceField>(++m_lastSeqNo);
184}
185
186void
187GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
188{
189 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
190}
191
192void
Eric Newberrya98bf932015-09-21 00:58:47 -0700193GenericLinkService::doReceivePacket(Transport::Packet&& packet)
194{
Eric Newberry86d31872015-09-23 16:24:59 -0700195 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700196 lp::Packet pkt(packet.packet);
197
Eric Newberry185ab292017-03-28 06:45:39 +0000198 if (m_options.reliabilityOptions.isEnabled) {
199 m_reliability.processIncomingPacket(pkt);
200 }
201
Eric Newberrya1939ba2015-10-09 12:35:03 -0700202 if (!pkt.has<lp::FragmentField>()) {
203 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
204 return;
205 }
206
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700207 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
208 !m_options.allowReassembly) {
209 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700210 return;
211 }
212
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700213 bool isReassembled = false;
214 Block netPkt;
215 lp::Packet firstPkt;
216 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
217 pkt);
218 if (isReassembled) {
219 this->decodeNetPacket(netPkt, firstPkt);
220 }
221 }
222 catch (const tlv::Error& e) {
223 ++this->nInLpInvalid;
224 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
225 }
226}
Eric Newberry86d31872015-09-23 16:24:59 -0700227
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700228void
229GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
230{
231 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700232 switch (netPkt.type()) {
233 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700234 if (firstPkt.has<lp::NackField>()) {
235 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700236 }
237 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700238 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700239 }
240 break;
241 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700242 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700243 break;
244 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700245 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700246 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
247 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700248 }
249 }
Eric Newberry86d31872015-09-23 16:24:59 -0700250 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700251 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700252 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
253 }
254}
255
Eric Newberry86d31872015-09-23 16:24:59 -0700256void
257GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
258{
259 BOOST_ASSERT(netPkt.type() == tlv::Interest);
260 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
261
262 // forwarding expects Interest to be created with make_shared
263 auto interest = make_shared<Interest>(netPkt);
264
265 if (firstPkt.has<lp::NextHopFaceIdField>()) {
266 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000267 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700268 }
269 else {
270 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
271 return;
272 }
273 }
274
275 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700276 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700277 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
278 return;
279 }
280
281 if (firstPkt.has<lp::IncomingFaceIdField>()) {
282 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
283 }
284
Eric Newberryee400b52016-11-24 14:12:48 +0000285 if (firstPkt.has<lp::CongestionMarkField>()) {
286 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
287 }
288
Eric Newberry86d31872015-09-23 16:24:59 -0700289 this->receiveInterest(*interest);
290}
291
292void
293GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
294{
295 BOOST_ASSERT(netPkt.type() == tlv::Data);
296
297 // forwarding expects Data to be created with make_shared
298 auto data = make_shared<Data>(netPkt);
299
300 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700301 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700302 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
303 return;
304 }
305
306 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700307 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700308 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
309 return;
310 }
311
312 if (firstPkt.has<lp::CachePolicyField>()) {
313 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000314 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
315 // so it's unnecessary to check here.
316 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700317 }
318 else {
319 NFD_LOG_FACE_WARN("received CachePolicy, but local fields disabled: IGNORE");
320 }
321 }
322
323 if (firstPkt.has<lp::IncomingFaceIdField>()) {
324 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
325 }
326
Eric Newberryee400b52016-11-24 14:12:48 +0000327 if (firstPkt.has<lp::CongestionMarkField>()) {
328 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
329 }
330
Eric Newberry86d31872015-09-23 16:24:59 -0700331 this->receiveData(*data);
332}
333
334void
335GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
336{
337 BOOST_ASSERT(netPkt.type() == tlv::Interest);
338 BOOST_ASSERT(firstPkt.has<lp::NackField>());
339
340 lp::Nack nack((Interest(netPkt)));
341 nack.setHeader(firstPkt.get<lp::NackField>());
342
343 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700344 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700345 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
346 return;
347 }
348
349 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700350 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700351 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
352 return;
353 }
354
355 if (firstPkt.has<lp::IncomingFaceIdField>()) {
356 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
357 }
358
Eric Newberryee400b52016-11-24 14:12:48 +0000359 if (firstPkt.has<lp::CongestionMarkField>()) {
360 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
361 }
362
Eric Newberry86d31872015-09-23 16:24:59 -0700363 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700364}
365
366} // namespace face
367} // namespace nfd