blob: 2a7f527cf1e4cebfafe244383da30758aca117f2 [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 }
Eric Newberry86d31872015-09-23 16:24:59 -0700101}
102
Eric Newberrya98bf932015-09-21 00:58:47 -0700103void
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700104GenericLinkService::sendNetPacket(lp::Packet&& pkt)
105{
106 std::vector<lp::Packet> frags;
107 const ssize_t mtu = this->getTransport()->getMtu();
108 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
109 bool isOk = false;
110 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
111 if (!isOk) {
112 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000113 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700114 return;
115 }
116 }
117 else {
118 frags.push_back(pkt);
119 }
120
121 if (frags.size() > 1) {
122 // sequence is needed only if packet is fragmented
Junxiao Shi0de23a22015-12-03 20:07:02 +0000123 this->assignSequences(frags);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700124 }
125 else {
126 // even if indexed fragmentation is enabled, the fragmenter should not
127 // fragment the packet if it can fit in MTU
128 BOOST_ASSERT(frags.size() > 0);
129 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
130 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
131 }
132
133 for (const lp::Packet& frag : frags) {
134 Transport::Packet tp(frag.wireEncode());
135 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000136 ++this->nOutOverMtu;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700137 NFD_LOG_FACE_WARN("attempt to send packet over MTU limit");
138 continue;
139 }
Junxiao Shi0de23a22015-12-03 20:07:02 +0000140 this->sendPacket(std::move(tp));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700141 }
142}
143
144void
145GenericLinkService::assignSequence(lp::Packet& pkt)
146{
147 pkt.set<lp::SequenceField>(++m_lastSeqNo);
148}
149
150void
151GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
152{
153 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
154}
155
156void
Eric Newberrya98bf932015-09-21 00:58:47 -0700157GenericLinkService::doReceivePacket(Transport::Packet&& packet)
158{
Eric Newberry86d31872015-09-23 16:24:59 -0700159 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700160 lp::Packet pkt(packet.packet);
161
162 if (!pkt.has<lp::FragmentField>()) {
163 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
164 return;
165 }
166
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700167 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
168 !m_options.allowReassembly) {
169 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700170 return;
171 }
172
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700173 bool isReassembled = false;
174 Block netPkt;
175 lp::Packet firstPkt;
176 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
177 pkt);
178 if (isReassembled) {
179 this->decodeNetPacket(netPkt, firstPkt);
180 }
181 }
182 catch (const tlv::Error& e) {
183 ++this->nInLpInvalid;
184 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
185 }
186}
Eric Newberry86d31872015-09-23 16:24:59 -0700187
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700188void
189GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
190{
191 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700192 switch (netPkt.type()) {
193 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700194 if (firstPkt.has<lp::NackField>()) {
195 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700196 }
197 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700198 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700199 }
200 break;
201 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700202 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700203 break;
204 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700205 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700206 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
207 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700208 }
209 }
Eric Newberry86d31872015-09-23 16:24:59 -0700210 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700211 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700212 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
213 }
214}
215
Eric Newberry86d31872015-09-23 16:24:59 -0700216void
217GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
218{
219 BOOST_ASSERT(netPkt.type() == tlv::Interest);
220 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
221
222 // forwarding expects Interest to be created with make_shared
223 auto interest = make_shared<Interest>(netPkt);
224
225 if (firstPkt.has<lp::NextHopFaceIdField>()) {
226 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000227 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700228 }
229 else {
230 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
231 return;
232 }
233 }
234
235 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700236 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700237 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
238 return;
239 }
240
241 if (firstPkt.has<lp::IncomingFaceIdField>()) {
242 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
243 }
244
Eric Newberryee400b52016-11-24 14:12:48 +0000245 if (firstPkt.has<lp::CongestionMarkField>()) {
246 interest->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
247 }
248
Eric Newberry86d31872015-09-23 16:24:59 -0700249 this->receiveInterest(*interest);
250}
251
252void
253GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
254{
255 BOOST_ASSERT(netPkt.type() == tlv::Data);
256
257 // forwarding expects Data to be created with make_shared
258 auto data = make_shared<Data>(netPkt);
259
260 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700261 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700262 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
263 return;
264 }
265
266 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700267 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700268 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
269 return;
270 }
271
272 if (firstPkt.has<lp::CachePolicyField>()) {
273 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000274 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
275 // so it's unnecessary to check here.
276 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700277 }
278 else {
279 NFD_LOG_FACE_WARN("received CachePolicy, but local fields disabled: IGNORE");
280 }
281 }
282
283 if (firstPkt.has<lp::IncomingFaceIdField>()) {
284 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
285 }
286
Eric Newberryee400b52016-11-24 14:12:48 +0000287 if (firstPkt.has<lp::CongestionMarkField>()) {
288 data->setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
289 }
290
Eric Newberry86d31872015-09-23 16:24:59 -0700291 this->receiveData(*data);
292}
293
294void
295GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
296{
297 BOOST_ASSERT(netPkt.type() == tlv::Interest);
298 BOOST_ASSERT(firstPkt.has<lp::NackField>());
299
300 lp::Nack nack((Interest(netPkt)));
301 nack.setHeader(firstPkt.get<lp::NackField>());
302
303 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700304 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700305 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
306 return;
307 }
308
309 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700310 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700311 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
312 return;
313 }
314
315 if (firstPkt.has<lp::IncomingFaceIdField>()) {
316 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
317 }
318
Eric Newberryee400b52016-11-24 14:12:48 +0000319 if (firstPkt.has<lp::CongestionMarkField>()) {
320 nack.setTag(make_shared<lp::CongestionMarkTag>(firstPkt.get<lp::CongestionMarkField>()));
321 }
322
Eric Newberry86d31872015-09-23 16:24:59 -0700323 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700324}
325
326} // namespace face
327} // namespace nfd