blob: 7ed58d260268e0f3c61cb80019280a50e7e21474 [file] [log] [blame]
Eric Newberrya98bf932015-09-21 00:58:47 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shicbc8e942016-09-06 03:17:45 +00003 * Copyright (c) 2014-2016, 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)
51 , m_lastSeqNo(-2)
Eric Newberry86d31872015-09-23 16:24:59 -070052{
Junxiao Shi0de23a22015-12-03 20:07:02 +000053 m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
Eric Newberry86d31872015-09-23 16:24:59 -070054}
55
Eric Newberrya98bf932015-09-21 00:58:47 -070056void
57GenericLinkService::doSendInterest(const Interest& interest)
58{
59 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000060
Eric Newberryee400b52016-11-24 14:12:48 +000061 encodeLpFields(interest, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070062
Junxiao Shi0de23a22015-12-03 20:07:02 +000063 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070064}
65
66void
67GenericLinkService::doSendData(const Data& data)
68{
69 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000070
Eric Newberryee400b52016-11-24 14:12:48 +000071 encodeLpFields(data, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070072
Junxiao Shi0de23a22015-12-03 20:07:02 +000073 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070074}
75
76void
77GenericLinkService::doSendNack(const lp::Nack& nack)
78{
79 lp::Packet lpPacket(nack.getInterest().wireEncode());
80 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +000081
Eric Newberryee400b52016-11-24 14:12:48 +000082 encodeLpFields(nack, lpPacket);
Eric Newberry4c3e6b82015-11-10 16:48:42 -070083
Junxiao Shi0de23a22015-12-03 20:07:02 +000084 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070085}
86
Junxiao Shi0de23a22015-12-03 20:07:02 +000087void
Eric Newberryee400b52016-11-24 14:12:48 +000088GenericLinkService::encodeLpFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -070089{
Eric Newberryee400b52016-11-24 14:12:48 +000090 if (m_options.allowLocalFields) {
91 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
92 if (incomingFaceIdTag != nullptr) {
93 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
94 }
95 }
96
97 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = netPkt.getTag<lp::CongestionMarkTag>();
98 if (congestionMarkTag != nullptr) {
99 lpPacket.add<lp::CongestionMarkField>(*congestionMarkTag);
Eric Newberry86d31872015-09-23 16:24:59 -0700100 }
Spyridon Mastorakisd0abae32016-12-06 15:20:19 -0800101
102 shared_ptr<lp::HopCountTag> hopCountTag = netPkt.getTag<lp::HopCountTag>();
103 if (hopCountTag != nullptr) {
104 lpPacket.add<lp::HopCountTagField>(*hopCountTag);
105 }
106 else {
107 lpPacket.add<lp::HopCountTagField>(0);
108 }
Eric Newberry86d31872015-09-23 16:24:59 -0700109}
110
Eric Newberrya98bf932015-09-21 00:58:47 -0700111void
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700112GenericLinkService::sendNetPacket(lp::Packet&& pkt)
113{
114 std::vector<lp::Packet> frags;
115 const ssize_t mtu = this->getTransport()->getMtu();
116 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
117 bool isOk = false;
118 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
119 if (!isOk) {
120 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000121 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700122 return;
123 }
124 }
125 else {
126 frags.push_back(pkt);
127 }
128
129 if (frags.size() > 1) {
130 // sequence is needed only if packet is fragmented
Junxiao Shi0de23a22015-12-03 20:07:02 +0000131 this->assignSequences(frags);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700132 }
133 else {
134 // even if indexed fragmentation is enabled, the fragmenter should not
135 // fragment the packet if it can fit in MTU
136 BOOST_ASSERT(frags.size() > 0);
137 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
138 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
139 }
140
141 for (const lp::Packet& frag : frags) {
142 Transport::Packet tp(frag.wireEncode());
143 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000144 ++this->nOutOverMtu;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700145 NFD_LOG_FACE_WARN("attempt to send packet over MTU limit");
146 continue;
147 }
Junxiao Shi0de23a22015-12-03 20:07:02 +0000148 this->sendPacket(std::move(tp));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700149 }
150}
151
152void
153GenericLinkService::assignSequence(lp::Packet& pkt)
154{
155 pkt.set<lp::SequenceField>(++m_lastSeqNo);
156}
157
158void
159GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
160{
161 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
162}
163
164void
Eric Newberrya98bf932015-09-21 00:58:47 -0700165GenericLinkService::doReceivePacket(Transport::Packet&& packet)
166{
Eric Newberry86d31872015-09-23 16:24:59 -0700167 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700168 lp::Packet pkt(packet.packet);
169
170 if (!pkt.has<lp::FragmentField>()) {
171 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
172 return;
173 }
174
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700175 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
176 !m_options.allowReassembly) {
177 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700178 return;
179 }
180
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700181 bool isReassembled = false;
182 Block netPkt;
183 lp::Packet firstPkt;
184 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
185 pkt);
186 if (isReassembled) {
187 this->decodeNetPacket(netPkt, firstPkt);
188 }
189 }
190 catch (const tlv::Error& e) {
191 ++this->nInLpInvalid;
192 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
193 }
194}
Eric Newberry86d31872015-09-23 16:24:59 -0700195
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700196void
197GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
198{
199 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700200 switch (netPkt.type()) {
201 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700202 if (firstPkt.has<lp::NackField>()) {
203 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700204 }
205 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700206 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700207 }
208 break;
209 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700210 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700211 break;
212 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700213 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700214 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
215 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700216 }
217 }
Eric Newberry86d31872015-09-23 16:24:59 -0700218 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700219 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700220 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
221 }
222}
223
Eric Newberry86d31872015-09-23 16:24:59 -0700224void
225GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
226{
227 BOOST_ASSERT(netPkt.type() == tlv::Interest);
228 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
229
230 // forwarding expects Interest to be created with make_shared
231 auto interest = make_shared<Interest>(netPkt);
232
Spyridon Mastorakisd0abae32016-12-06 15:20:19 -0800233 // Increment HopCount
234 if (firstPkt.has<lp::HopCountTagField>()) {
235 interest->setTag(make_shared<lp::HopCountTag>(firstPkt.get<lp::HopCountTagField>() + 1));
236 }
237
Eric Newberry86d31872015-09-23 16:24:59 -0700238 if (firstPkt.has<lp::NextHopFaceIdField>()) {
239 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000240 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700241 }
242 else {
243 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
244 return;
245 }
246 }
247
248 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700249 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700250 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
251 return;
252 }
253
254 if (firstPkt.has<lp::IncomingFaceIdField>()) {
255 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
256 }
257
Eric Newberryee400b52016-11-24 14:12:48 +0000258 if (firstPkt.has<lp::CongestionMarkField>()) {
259 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
260 }
261
Eric Newberry86d31872015-09-23 16:24:59 -0700262 this->receiveInterest(*interest);
263}
264
265void
266GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
267{
268 BOOST_ASSERT(netPkt.type() == tlv::Data);
269
270 // forwarding expects Data to be created with make_shared
271 auto data = make_shared<Data>(netPkt);
272
Spyridon Mastorakisd0abae32016-12-06 15:20:19 -0800273 if (firstPkt.has<lp::HopCountTagField>()) {
274 data->setTag(make_shared<lp::HopCountTag>(firstPkt.get<lp::HopCountTagField>() + 1));
275 }
276
Eric Newberry86d31872015-09-23 16:24:59 -0700277 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700278 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700279 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
280 return;
281 }
282
283 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700284 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700285 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
286 return;
287 }
288
289 if (firstPkt.has<lp::CachePolicyField>()) {
290 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000291 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
292 // so it's unnecessary to check here.
293 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700294 }
295 else {
296 NFD_LOG_FACE_WARN("received CachePolicy, but local fields disabled: IGNORE");
297 }
298 }
299
300 if (firstPkt.has<lp::IncomingFaceIdField>()) {
301 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
302 }
303
Eric Newberryee400b52016-11-24 14:12:48 +0000304 if (firstPkt.has<lp::CongestionMarkField>()) {
305 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
306 }
307
Eric Newberry86d31872015-09-23 16:24:59 -0700308 this->receiveData(*data);
309}
310
311void
312GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
313{
314 BOOST_ASSERT(netPkt.type() == tlv::Interest);
315 BOOST_ASSERT(firstPkt.has<lp::NackField>());
316
317 lp::Nack nack((Interest(netPkt)));
318 nack.setHeader(firstPkt.get<lp::NackField>());
319
320 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700321 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700322 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
323 return;
324 }
325
326 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700327 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700328 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
329 return;
330 }
331
332 if (firstPkt.has<lp::IncomingFaceIdField>()) {
333 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
334 }
335
Eric Newberryee400b52016-11-24 14:12:48 +0000336 if (firstPkt.has<lp::CongestionMarkField>()) {
337 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
338 }
339
Eric Newberry86d31872015-09-23 16:24:59 -0700340 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700341}
342
343} // namespace face
344} // namespace nfd