blob: 5a3664c5d4a0343875e135e4aa162d2d96af53f2 [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/*
Davide Pesaventoa8098582019-03-31 15:48:02 -04003 * Copyright (c) 2014-2019, 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"
Eric Newberryb49313d2017-12-24 20:22:27 -070027
Junxiao Shicbc8e942016-09-06 03:17:45 +000028#include <ndn-cxx/lp/tags.hpp>
Eric Newberrya98bf932015-09-21 00:58:47 -070029
Eric Newberryb49313d2017-12-24 20:22:27 -070030#include <cmath>
31
Eric Newberrya98bf932015-09-21 00:58:47 -070032namespace nfd {
33namespace face {
34
Davide Pesaventoa3148082018-04-12 18:21:54 -040035NFD_LOG_INIT(GenericLinkService);
Eric Newberrya98bf932015-09-21 00:58:47 -070036
Davide Pesaventoa8098582019-03-31 15:48:02 -040037constexpr size_t CONGESTION_MARK_SIZE = tlv::sizeOfVarNumber(lp::tlv::CongestionMark) + // type
38 tlv::sizeOfVarNumber(sizeof(uint64_t)) + // length
39 tlv::sizeOfNonNegativeInteger(UINT64_MAX); // value
40
Eric Newberryb49313d2017-12-24 20:22:27 -070041constexpr uint32_t DEFAULT_CONGESTION_THRESHOLD_DIVISOR = 2;
42
Eric Newberry86d31872015-09-23 16:24:59 -070043GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
Eric Newberry73bcad32017-04-25 17:57:35 -070044 : m_options(options)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070045 , m_fragmenter(m_options.fragmenterOptions, this)
46 , m_reassembler(m_options.reassemblerOptions, this)
Eric Newberry185ab292017-03-28 06:45:39 +000047 , m_reliability(m_options.reliabilityOptions, this)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070048 , m_lastSeqNo(-2)
Eric Newberryb49313d2017-12-24 20:22:27 -070049 , m_nextMarkTime(time::steady_clock::TimePoint::max())
50 , m_lastMarkTime(time::steady_clock::TimePoint::min())
51 , m_nMarkedSinceInMarkingState(0)
Eric Newberry86d31872015-09-23 16:24:59 -070052{
Davide Pesaventoe4b22382018-06-10 14:37:24 -040053 m_reassembler.beforeTimeout.connect([this] (auto...) { ++this->nReassemblyTimeouts; });
54 m_reliability.onDroppedInterest.connect([this] (const auto& i) { this->notifyDroppedInterest(i); });
Eric Newberry73bcad32017-04-25 17:57:35 -070055 nReassembling.observe(&m_reassembler);
Eric Newberry86d31872015-09-23 16:24:59 -070056}
57
Eric Newberrya98bf932015-09-21 00:58:47 -070058void
Eric Newberry185ab292017-03-28 06:45:39 +000059GenericLinkService::setOptions(const GenericLinkService::Options& options)
60{
61 m_options = options;
62 m_fragmenter.setOptions(m_options.fragmenterOptions);
63 m_reassembler.setOptions(m_options.reassemblerOptions);
64 m_reliability.setOptions(m_options.reliabilityOptions);
65}
66
67void
ashiqopu075bb7d2019-03-10 01:38:21 +000068GenericLinkService::requestIdlePacket(const EndpointId& endpointId)
Eric Newberry185ab292017-03-28 06:45:39 +000069{
70 // No need to request Acks to attach to this packet from LpReliability, as they are already
71 // attached in sendLpPacket
ashiqopu075bb7d2019-03-10 01:38:21 +000072 this->sendLpPacket({}, endpointId);
Eric Newberry185ab292017-03-28 06:45:39 +000073}
74
75void
ashiqopu075bb7d2019-03-10 01:38:21 +000076GenericLinkService::sendLpPacket(lp::Packet&& pkt, const EndpointId& endpointId)
Eric Newberry185ab292017-03-28 06:45:39 +000077{
78 const ssize_t mtu = this->getTransport()->getMtu();
Eric Newberryb49313d2017-12-24 20:22:27 -070079
Eric Newberry185ab292017-03-28 06:45:39 +000080 if (m_options.reliabilityOptions.isEnabled) {
81 m_reliability.piggyback(pkt, mtu);
82 }
83
Eric Newberryb49313d2017-12-24 20:22:27 -070084 if (m_options.allowCongestionMarking) {
85 checkCongestionLevel(pkt);
86 }
87
Davide Pesaventob3a23ca2019-05-04 20:40:21 -040088 auto block = pkt.wireEncode();
89 if (mtu != MTU_UNLIMITED && block.size() > static_cast<size_t>(mtu)) {
Eric Newberry185ab292017-03-28 06:45:39 +000090 ++this->nOutOverMtu;
91 NFD_LOG_FACE_WARN("attempted to send packet over MTU limit");
92 return;
93 }
Davide Pesaventob3a23ca2019-05-04 20:40:21 -040094 this->sendPacket(block, endpointId);
Eric Newberry185ab292017-03-28 06:45:39 +000095}
96
97void
ashiqopu075bb7d2019-03-10 01:38:21 +000098GenericLinkService::doSendInterest(const Interest& interest, const EndpointId& endpointId)
Eric Newberrya98bf932015-09-21 00:58:47 -070099{
100 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000101
Eric Newberryee400b52016-11-24 14:12:48 +0000102 encodeLpFields(interest, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700103
ashiqopu075bb7d2019-03-10 01:38:21 +0000104 this->sendNetPacket(std::move(lpPacket), endpointId, true);
Eric Newberrya98bf932015-09-21 00:58:47 -0700105}
106
107void
ashiqopu075bb7d2019-03-10 01:38:21 +0000108GenericLinkService::doSendData(const Data& data, const EndpointId& endpointId)
Eric Newberrya98bf932015-09-21 00:58:47 -0700109{
110 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000111
Eric Newberryee400b52016-11-24 14:12:48 +0000112 encodeLpFields(data, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700113
ashiqopu075bb7d2019-03-10 01:38:21 +0000114 this->sendNetPacket(std::move(lpPacket), endpointId, false);
Eric Newberrya98bf932015-09-21 00:58:47 -0700115}
116
117void
ashiqopu075bb7d2019-03-10 01:38:21 +0000118GenericLinkService::doSendNack(const lp::Nack& nack, const EndpointId& endpointId)
Eric Newberrya98bf932015-09-21 00:58:47 -0700119{
120 lp::Packet lpPacket(nack.getInterest().wireEncode());
121 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +0000122
Eric Newberryee400b52016-11-24 14:12:48 +0000123 encodeLpFields(nack, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700124
ashiqopu075bb7d2019-03-10 01:38:21 +0000125 this->sendNetPacket(std::move(lpPacket), endpointId, false);
Eric Newberrya98bf932015-09-21 00:58:47 -0700126}
127
Junxiao Shi0de23a22015-12-03 20:07:02 +0000128void
Eric Newberry41aba102017-11-01 16:42:13 -0700129GenericLinkService::encodeLpFields(const ndn::PacketBase& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -0700130{
Eric Newberryee400b52016-11-24 14:12:48 +0000131 if (m_options.allowLocalFields) {
132 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
133 if (incomingFaceIdTag != nullptr) {
134 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
135 }
136 }
137
138 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
139 if (congestionMarkTag != nullptr) {
140 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
Eric Newberry86d31872015-09-23 16:24:59 -0700141 }
Teng Liangfdcbb4d2018-01-27 16:01:35 -0700142
143 if (m_options.allowSelfLearning) {
144 shared_ptr<lp::NonDiscoveryTag> nonDiscoveryTag = netPkt.getTag<lp::NonDiscoveryTag>();
145 if (nonDiscoveryTag != nullptr) {
146 lpPacket.add<lp::NonDiscoveryField>(*nonDiscoveryTag);
147 }
148
149 shared_ptr<lp::PrefixAnnouncementTag> prefixAnnouncementTag = netPkt.getTag<lp::PrefixAnnouncementTag>();
150 if (prefixAnnouncementTag != nullptr) {
151 lpPacket.add<lp::PrefixAnnouncementField>(*prefixAnnouncementTag);
152 }
153 }
Eric Newberry86d31872015-09-23 16:24:59 -0700154}
155
Eric Newberrya98bf932015-09-21 00:58:47 -0700156void
ashiqopu075bb7d2019-03-10 01:38:21 +0000157GenericLinkService::sendNetPacket(lp::Packet&& pkt, const EndpointId& endpointId, bool isInterest)
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700158{
159 std::vector<lp::Packet> frags;
Eric Newberry7b0071e2017-07-03 17:33:31 +0000160 ssize_t mtu = this->getTransport()->getMtu();
161
162 // Make space for feature fields in fragments
163 if (m_options.reliabilityOptions.isEnabled && mtu != MTU_UNLIMITED) {
164 mtu -= LpReliability::RESERVED_HEADER_SPACE;
Eric Newberry7b0071e2017-07-03 17:33:31 +0000165 }
166
Eric Newberryb49313d2017-12-24 20:22:27 -0700167 if (m_options.allowCongestionMarking && mtu != MTU_UNLIMITED) {
168 mtu -= CONGESTION_MARK_SIZE;
169 }
170
171 BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu > 0);
172
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700173 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
174 bool isOk = false;
175 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
176 if (!isOk) {
177 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000178 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700179 return;
180 }
181 }
182 else {
Eric Newberry41aba102017-11-01 16:42:13 -0700183 if (m_options.reliabilityOptions.isEnabled) {
184 frags.push_back(pkt);
185 }
186 else {
187 frags.push_back(std::move(pkt));
188 }
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700189 }
190
Eric Newberry185ab292017-03-28 06:45:39 +0000191 if (frags.size() == 1) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700192 // even if indexed fragmentation is enabled, the fragmenter should not
193 // fragment the packet if it can fit in MTU
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700194 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
195 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
196 }
197
Eric Newberry7b0071e2017-07-03 17:33:31 +0000198 // Only assign sequences to fragments if packet contains more than 1 fragment
199 if (frags.size() > 1) {
Eric Newberry185ab292017-03-28 06:45:39 +0000200 // Assign sequences to all fragments
201 this->assignSequences(frags);
202 }
203
204 if (m_options.reliabilityOptions.isEnabled && frags.front().has<lp::FragmentField>()) {
Eric Newberry41aba102017-11-01 16:42:13 -0700205 m_reliability.handleOutgoing(frags, std::move(pkt), isInterest);
Eric Newberry185ab292017-03-28 06:45:39 +0000206 }
207
208 for (lp::Packet& frag : frags) {
ashiqopu075bb7d2019-03-10 01:38:21 +0000209 this->sendLpPacket(std::move(frag), endpointId);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700210 }
211}
212
213void
214GenericLinkService::assignSequence(lp::Packet& pkt)
215{
216 pkt.set<lp::SequenceField>(++m_lastSeqNo);
217}
218
219void
220GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
221{
Davide Pesaventoe4b22382018-06-10 14:37:24 -0400222 std::for_each(pkts.begin(), pkts.end(), [this] (auto& pkt) { this->assignSequence(pkt); });
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700223}
224
225void
Eric Newberryb49313d2017-12-24 20:22:27 -0700226GenericLinkService::checkCongestionLevel(lp::Packet& pkt)
227{
228 ssize_t sendQueueLength = getTransport()->getSendQueueLength();
229 // This operation requires that the transport supports retrieving current send queue length
230 if (sendQueueLength < 0) {
231 return;
232 }
233
234 // To avoid overflowing the queue, set the congestion threshold to at least half of the send
235 // queue capacity.
236 size_t congestionThreshold = m_options.defaultCongestionThreshold;
237 if (getTransport()->getSendQueueCapacity() >= 0) {
238 congestionThreshold = std::min(congestionThreshold,
239 static_cast<size_t>(getTransport()->getSendQueueCapacity()) /
240 DEFAULT_CONGESTION_THRESHOLD_DIVISOR);
241 }
242
243 if (sendQueueLength > 0) {
244 NFD_LOG_FACE_TRACE("txqlen=" << sendQueueLength << " threshold=" << congestionThreshold <<
245 " capacity=" << getTransport()->getSendQueueCapacity());
246 }
247
248 if (static_cast<size_t>(sendQueueLength) > congestionThreshold) { // Send queue is congested
249 const auto now = time::steady_clock::now();
250 if (now >= m_nextMarkTime || now >= m_lastMarkTime + m_options.baseCongestionMarkingInterval) {
251 // Mark at most one initial packet per baseCongestionMarkingInterval
252 if (m_nMarkedSinceInMarkingState == 0) {
253 m_nextMarkTime = now;
254 }
255
256 // Time to mark packet
257 pkt.set<lp::CongestionMarkField>(1);
258 ++nCongestionMarked;
259 NFD_LOG_FACE_DEBUG("LpPacket was marked as congested");
260
261 ++m_nMarkedSinceInMarkingState;
262 // Decrease the marking interval by the inverse of the square root of the number of packets
263 // marked in this incident of congestion
264 m_nextMarkTime += time::nanoseconds(static_cast<time::nanoseconds::rep>(
265 m_options.baseCongestionMarkingInterval.count() /
266 std::sqrt(m_nMarkedSinceInMarkingState)));
267 m_lastMarkTime = now;
268 }
269 }
270 else if (m_nextMarkTime != time::steady_clock::TimePoint::max()) {
271 // Congestion incident has ended, so reset
272 NFD_LOG_FACE_DEBUG("Send queue length dropped below congestion threshold");
273 m_nextMarkTime = time::steady_clock::TimePoint::max();
274 m_nMarkedSinceInMarkingState = 0;
275 }
276}
277
278void
Davide Pesaventob3a23ca2019-05-04 20:40:21 -0400279GenericLinkService::doReceivePacket(const Block& packet, const EndpointId& endpoint)
Eric Newberrya98bf932015-09-21 00:58:47 -0700280{
Eric Newberry86d31872015-09-23 16:24:59 -0700281 try {
Davide Pesaventob3a23ca2019-05-04 20:40:21 -0400282 lp::Packet pkt(packet);
Eric Newberrya1939ba2015-10-09 12:35:03 -0700283
Eric Newberry185ab292017-03-28 06:45:39 +0000284 if (m_options.reliabilityOptions.isEnabled) {
285 m_reliability.processIncomingPacket(pkt);
286 }
287
Eric Newberrya1939ba2015-10-09 12:35:03 -0700288 if (!pkt.has<lp::FragmentField>()) {
289 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
290 return;
291 }
292
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700293 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
294 !m_options.allowReassembly) {
295 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700296 return;
297 }
298
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700299 bool isReassembled = false;
300 Block netPkt;
301 lp::Packet firstPkt;
Davide Pesaventob3a23ca2019-05-04 20:40:21 -0400302 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(endpoint, pkt);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700303 if (isReassembled) {
Davide Pesaventob3a23ca2019-05-04 20:40:21 -0400304 this->decodeNetPacket(netPkt, firstPkt, endpoint);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700305 }
306 }
307 catch (const tlv::Error& e) {
308 ++this->nInLpInvalid;
309 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
310 }
311}
Eric Newberry86d31872015-09-23 16:24:59 -0700312
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700313void
ashiqopu075bb7d2019-03-10 01:38:21 +0000314GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt,
315 const EndpointId& endpointId)
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700316{
317 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700318 switch (netPkt.type()) {
319 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700320 if (firstPkt.has<lp::NackField>()) {
ashiqopu075bb7d2019-03-10 01:38:21 +0000321 this->decodeNack(netPkt, firstPkt, endpointId);
Eric Newberry86d31872015-09-23 16:24:59 -0700322 }
323 else {
ashiqopu075bb7d2019-03-10 01:38:21 +0000324 this->decodeInterest(netPkt, firstPkt, endpointId);
Eric Newberry86d31872015-09-23 16:24:59 -0700325 }
326 break;
327 case tlv::Data:
ashiqopu075bb7d2019-03-10 01:38:21 +0000328 this->decodeData(netPkt, firstPkt, endpointId);
Eric Newberry86d31872015-09-23 16:24:59 -0700329 break;
330 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700331 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700332 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
333 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700334 }
335 }
Eric Newberry86d31872015-09-23 16:24:59 -0700336 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700337 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700338 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
339 }
340}
341
Eric Newberry86d31872015-09-23 16:24:59 -0700342void
ashiqopu075bb7d2019-03-10 01:38:21 +0000343GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt,
344 const EndpointId& endpointId)
Eric Newberry86d31872015-09-23 16:24:59 -0700345{
346 BOOST_ASSERT(netPkt.type() == tlv::Interest);
347 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
348
349 // forwarding expects Interest to be created with make_shared
350 auto interest = make_shared<Interest>(netPkt);
351
352 if (firstPkt.has<lp::NextHopFaceIdField>()) {
353 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000354 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700355 }
356 else {
357 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
358 return;
359 }
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 Interest: 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 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
374 }
375
Teng Liangfdcbb4d2018-01-27 16:01:35 -0700376 if (firstPkt.has<lp::NonDiscoveryField>()) {
377 if (m_options.allowSelfLearning) {
378 interest->setTag(make_shared<lp::NonDiscoveryTag>(firstPkt.get<lp::NonDiscoveryField>()));
379 }
380 else {
381 NFD_LOG_FACE_WARN("received NonDiscovery, but self-learning disabled: IGNORE");
382 }
383 }
384
385 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
386 ++this->nInNetInvalid;
387 NFD_LOG_FACE_WARN("received PrefixAnnouncement with Interest: DROP");
388 return;
389 }
390
ashiqopu075bb7d2019-03-10 01:38:21 +0000391 this->receiveInterest(*interest, endpointId);
Eric Newberry86d31872015-09-23 16:24:59 -0700392}
393
394void
ashiqopu075bb7d2019-03-10 01:38:21 +0000395GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt,
396 const EndpointId& endpointId)
Eric Newberry86d31872015-09-23 16:24:59 -0700397{
398 BOOST_ASSERT(netPkt.type() == tlv::Data);
399
400 // forwarding expects Data to be created with make_shared
401 auto data = make_shared<Data>(netPkt);
402
403 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700404 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700405 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
406 return;
407 }
408
409 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700410 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700411 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
412 return;
413 }
414
415 if (firstPkt.has<lp::CachePolicyField>()) {
Junxiao Shi6eb02712017-05-27 22:48:02 +0000416 // CachePolicy is unprivileged and does not require allowLocalFields option.
417 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
418 // so it's unnecessary to check here.
419 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700420 }
421
422 if (firstPkt.has<lp::IncomingFaceIdField>()) {
423 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
424 }
425
Eric Newberryee400b52016-11-24 14:12:48 +0000426 if (firstPkt.has<lp::CongestionMarkField>()) {
427 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
428 }
429
Teng Liangfdcbb4d2018-01-27 16:01:35 -0700430 if (firstPkt.has<lp::NonDiscoveryField>()) {
431 ++this->nInNetInvalid;
432 NFD_LOG_FACE_WARN("received NonDiscovery with Data: DROP");
433 return;
434 }
435
436 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
437 if (m_options.allowSelfLearning) {
438 data->setTag(make_shared<lp::PrefixAnnouncementTag>(firstPkt.get<lp::PrefixAnnouncementField>()));
439 }
440 else {
441 NFD_LOG_FACE_WARN("received PrefixAnnouncement, but self-learning disabled: IGNORE");
442 }
443 }
444
ashiqopu075bb7d2019-03-10 01:38:21 +0000445 this->receiveData(*data, endpointId);
Eric Newberry86d31872015-09-23 16:24:59 -0700446}
447
448void
ashiqopu075bb7d2019-03-10 01:38:21 +0000449GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt,
450 const EndpointId& endpointId)
Eric Newberry86d31872015-09-23 16:24:59 -0700451{
452 BOOST_ASSERT(netPkt.type() == tlv::Interest);
453 BOOST_ASSERT(firstPkt.has<lp::NackField>());
454
455 lp::Nack nack((Interest(netPkt)));
456 nack.setHeader(firstPkt.get<lp::NackField>());
457
458 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700459 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700460 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
461 return;
462 }
463
464 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700465 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700466 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
467 return;
468 }
469
470 if (firstPkt.has<lp::IncomingFaceIdField>()) {
471 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
472 }
473
Eric Newberryee400b52016-11-24 14:12:48 +0000474 if (firstPkt.has<lp::CongestionMarkField>()) {
475 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
476 }
477
Teng Liangfdcbb4d2018-01-27 16:01:35 -0700478 if (firstPkt.has<lp::NonDiscoveryField>()) {
479 ++this->nInNetInvalid;
480 NFD_LOG_FACE_WARN("received NonDiscovery with Nack: DROP");
481 return;
482 }
483
484 if (firstPkt.has<lp::PrefixAnnouncementField>()) {
485 ++this->nInNetInvalid;
486 NFD_LOG_FACE_WARN("received PrefixAnnouncement with Nack: DROP");
487 return;
488 }
489
ashiqopu075bb7d2019-03-10 01:38:21 +0000490 this->receiveNack(nack, endpointId);
Eric Newberrya98bf932015-09-21 00:58:47 -0700491}
492
493} // namespace face
494} // namespace nfd