blob: d1536ce90f2ee91572b8e3d155bddf8e7f9184ff [file] [log] [blame]
Eric Newberrya98bf932015-09-21 00:58:47 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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"
27
28namespace nfd {
29namespace face {
30
31NFD_LOG_INIT("GenericLinkService");
32
Eric Newberry4c3e6b82015-11-10 16:48:42 -070033GenericLinkServiceCounters::GenericLinkServiceCounters(const LpReassembler& reassembler)
34 : nReassembling(reassembler)
35{
36}
37
Eric Newberry86d31872015-09-23 16:24:59 -070038GenericLinkService::Options::Options()
39 : allowLocalFields(false)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070040 , allowFragmentation(false)
41 , allowReassembly(false)
Eric Newberry86d31872015-09-23 16:24:59 -070042{
43}
44
45GenericLinkService::GenericLinkService(const GenericLinkService::Options& options)
Eric Newberry4c3e6b82015-11-10 16:48:42 -070046 : GenericLinkServiceCounters(m_reassembler)
47 , m_options(options)
48 , m_fragmenter(m_options.fragmenterOptions, this)
49 , m_reassembler(m_options.reassemblerOptions, this)
50 , m_lastSeqNo(-2)
Eric Newberry86d31872015-09-23 16:24:59 -070051{
Junxiao Shi0de23a22015-12-03 20:07:02 +000052 m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
Eric Newberry86d31872015-09-23 16:24:59 -070053}
54
Eric Newberrya98bf932015-09-21 00:58:47 -070055void
56GenericLinkService::doSendInterest(const Interest& interest)
57{
58 lp::Packet lpPacket(interest.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000059
Eric Newberry86d31872015-09-23 16:24:59 -070060 if (m_options.allowLocalFields) {
61 encodeLocalFields(interest, lpPacket);
62 }
Eric Newberry4c3e6b82015-11-10 16:48:42 -070063
Junxiao Shi0de23a22015-12-03 20:07:02 +000064 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070065}
66
67void
68GenericLinkService::doSendData(const Data& data)
69{
70 lp::Packet lpPacket(data.wireEncode());
Junxiao Shi0de23a22015-12-03 20:07:02 +000071
Eric Newberry86d31872015-09-23 16:24:59 -070072 if (m_options.allowLocalFields) {
73 encodeLocalFields(data, lpPacket);
74 }
Eric Newberry4c3e6b82015-11-10 16:48:42 -070075
Junxiao Shi0de23a22015-12-03 20:07:02 +000076 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070077}
78
79void
80GenericLinkService::doSendNack(const lp::Nack& nack)
81{
82 lp::Packet lpPacket(nack.getInterest().wireEncode());
83 lpPacket.add<lp::NackField>(nack.getHeader());
Junxiao Shi0de23a22015-12-03 20:07:02 +000084
Eric Newberry86d31872015-09-23 16:24:59 -070085 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +000086 encodeLocalFields(nack, lpPacket);
Eric Newberry86d31872015-09-23 16:24:59 -070087 }
Eric Newberry4c3e6b82015-11-10 16:48:42 -070088
Junxiao Shi0de23a22015-12-03 20:07:02 +000089 this->sendNetPacket(std::move(lpPacket));
Eric Newberrya98bf932015-09-21 00:58:47 -070090}
91
Junxiao Shi0de23a22015-12-03 20:07:02 +000092void
93GenericLinkService::encodeLocalFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
Eric Newberry86d31872015-09-23 16:24:59 -070094{
Junxiao Shi0de23a22015-12-03 20:07:02 +000095 shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
96 if (incomingFaceIdTag != nullptr) {
97 lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
Eric Newberry86d31872015-09-23 16:24:59 -070098 }
Eric Newberry86d31872015-09-23 16:24:59 -070099}
100
Eric Newberrya98bf932015-09-21 00:58:47 -0700101void
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700102GenericLinkService::sendNetPacket(lp::Packet&& pkt)
103{
104 std::vector<lp::Packet> frags;
105 const ssize_t mtu = this->getTransport()->getMtu();
106 if (m_options.allowFragmentation && mtu != MTU_UNLIMITED) {
107 bool isOk = false;
108 std::tie(isOk, frags) = m_fragmenter.fragmentPacket(pkt, mtu);
109 if (!isOk) {
110 // fragmentation failed (warning is logged by LpFragmenter)
Junxiao Shi0de23a22015-12-03 20:07:02 +0000111 ++this->nFragmentationErrors;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700112 return;
113 }
114 }
115 else {
116 frags.push_back(pkt);
117 }
118
119 if (frags.size() > 1) {
120 // sequence is needed only if packet is fragmented
Junxiao Shi0de23a22015-12-03 20:07:02 +0000121 this->assignSequences(frags);
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700122 }
123 else {
124 // even if indexed fragmentation is enabled, the fragmenter should not
125 // fragment the packet if it can fit in MTU
126 BOOST_ASSERT(frags.size() > 0);
127 BOOST_ASSERT(!frags.front().has<lp::FragIndexField>());
128 BOOST_ASSERT(!frags.front().has<lp::FragCountField>());
129 }
130
131 for (const lp::Packet& frag : frags) {
132 Transport::Packet tp(frag.wireEncode());
133 if (mtu != MTU_UNLIMITED && tp.packet.size() > static_cast<size_t>(mtu)) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000134 ++this->nOutOverMtu;
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700135 NFD_LOG_FACE_WARN("attempt to send packet over MTU limit");
136 continue;
137 }
Junxiao Shi0de23a22015-12-03 20:07:02 +0000138 this->sendPacket(std::move(tp));
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700139 }
140}
141
142void
143GenericLinkService::assignSequence(lp::Packet& pkt)
144{
145 pkt.set<lp::SequenceField>(++m_lastSeqNo);
146}
147
148void
149GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
150{
151 std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
152}
153
154void
Eric Newberrya98bf932015-09-21 00:58:47 -0700155GenericLinkService::doReceivePacket(Transport::Packet&& packet)
156{
Eric Newberry86d31872015-09-23 16:24:59 -0700157 try {
Eric Newberrya1939ba2015-10-09 12:35:03 -0700158 lp::Packet pkt(packet.packet);
159
160 if (!pkt.has<lp::FragmentField>()) {
161 NFD_LOG_FACE_TRACE("received IDLE packet: DROP");
162 return;
163 }
164
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700165 if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
166 !m_options.allowReassembly) {
167 NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
Eric Newberrya1939ba2015-10-09 12:35:03 -0700168 return;
169 }
170
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700171 bool isReassembled = false;
172 Block netPkt;
173 lp::Packet firstPkt;
174 std::tie(isReassembled, netPkt, firstPkt) = m_reassembler.receiveFragment(packet.remoteEndpoint,
175 pkt);
176 if (isReassembled) {
177 this->decodeNetPacket(netPkt, firstPkt);
178 }
179 }
180 catch (const tlv::Error& e) {
181 ++this->nInLpInvalid;
182 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
183 }
184}
Eric Newberry86d31872015-09-23 16:24:59 -0700185
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700186void
187GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
188{
189 try {
Eric Newberry86d31872015-09-23 16:24:59 -0700190 switch (netPkt.type()) {
191 case tlv::Interest:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700192 if (firstPkt.has<lp::NackField>()) {
193 this->decodeNack(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700194 }
195 else {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700196 this->decodeInterest(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700197 }
198 break;
199 case tlv::Data:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700200 this->decodeData(netPkt, firstPkt);
Eric Newberry86d31872015-09-23 16:24:59 -0700201 break;
202 default:
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700203 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700204 NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
205 return;
Eric Newberrya98bf932015-09-21 00:58:47 -0700206 }
207 }
Eric Newberry86d31872015-09-23 16:24:59 -0700208 catch (const tlv::Error& e) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700209 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700210 NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
211 }
212}
213
Eric Newberry86d31872015-09-23 16:24:59 -0700214void
215GenericLinkService::decodeInterest(const Block& netPkt, const lp::Packet& firstPkt)
216{
217 BOOST_ASSERT(netPkt.type() == tlv::Interest);
218 BOOST_ASSERT(!firstPkt.has<lp::NackField>());
219
220 // forwarding expects Interest to be created with make_shared
221 auto interest = make_shared<Interest>(netPkt);
222
223 if (firstPkt.has<lp::NextHopFaceIdField>()) {
224 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000225 interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700226 }
227 else {
228 NFD_LOG_FACE_WARN("received NextHopFaceId, but local fields disabled: DROP");
229 return;
230 }
231 }
232
233 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700234 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700235 NFD_LOG_FACE_WARN("received CachePolicy with Interest: DROP");
236 return;
237 }
238
239 if (firstPkt.has<lp::IncomingFaceIdField>()) {
240 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
241 }
242
243 this->receiveInterest(*interest);
244}
245
246void
247GenericLinkService::decodeData(const Block& netPkt, const lp::Packet& firstPkt)
248{
249 BOOST_ASSERT(netPkt.type() == tlv::Data);
250
251 // forwarding expects Data to be created with make_shared
252 auto data = make_shared<Data>(netPkt);
253
254 if (firstPkt.has<lp::NackField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700255 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700256 NFD_LOG_FACE_WARN("received Nack with Data: DROP");
257 return;
258 }
259
260 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700261 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700262 NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
263 return;
264 }
265
266 if (firstPkt.has<lp::CachePolicyField>()) {
267 if (m_options.allowLocalFields) {
Junxiao Shi0de23a22015-12-03 20:07:02 +0000268 // In case of an invalid CachePolicyType, get<lp::CachePolicyField> will throw,
269 // so it's unnecessary to check here.
270 data->setTag(make_shared<lp::CachePolicyTag>(firstPkt.get<lp::CachePolicyField>()));
Eric Newberry86d31872015-09-23 16:24:59 -0700271 }
272 else {
273 NFD_LOG_FACE_WARN("received CachePolicy, but local fields disabled: IGNORE");
274 }
275 }
276
277 if (firstPkt.has<lp::IncomingFaceIdField>()) {
278 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
279 }
280
281 this->receiveData(*data);
282}
283
284void
285GenericLinkService::decodeNack(const Block& netPkt, const lp::Packet& firstPkt)
286{
287 BOOST_ASSERT(netPkt.type() == tlv::Interest);
288 BOOST_ASSERT(firstPkt.has<lp::NackField>());
289
290 lp::Nack nack((Interest(netPkt)));
291 nack.setHeader(firstPkt.get<lp::NackField>());
292
293 if (firstPkt.has<lp::NextHopFaceIdField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700294 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700295 NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
296 return;
297 }
298
299 if (firstPkt.has<lp::CachePolicyField>()) {
Eric Newberry4c3e6b82015-11-10 16:48:42 -0700300 ++this->nInNetInvalid;
Eric Newberry86d31872015-09-23 16:24:59 -0700301 NFD_LOG_FACE_WARN("received CachePolicy with Nack: DROP");
302 return;
303 }
304
305 if (firstPkt.has<lp::IncomingFaceIdField>()) {
306 NFD_LOG_FACE_WARN("received IncomingFaceId: IGNORE");
307 }
308
309 this->receiveNack(nack);
Eric Newberrya98bf932015-09-21 00:58:47 -0700310}
311
312} // namespace face
313} // namespace nfd