NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
generic-link-service.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "generic-link-service.hpp"
27 
28 namespace nfd {
29 namespace face {
30 
31 NFD_LOG_INIT("GenericLinkService");
32 
34  : nReassembling(reassembler)
35 {
36 }
37 
39  : allowLocalFields(false)
40  , allowFragmentation(false)
41  , allowReassembly(false)
42 {
43 }
44 
46  : 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)
51 {
52  m_reassembler.beforeTimeout.connect(bind([this] { ++this->nReassemblyTimeouts; }));
53 }
54 
55 void
56 GenericLinkService::doSendInterest(const Interest& interest)
57 {
58  lp::Packet lpPacket(interest.wireEncode());
59 
60  if (m_options.allowLocalFields) {
61  encodeLocalFields(interest, lpPacket);
62  }
63 
64  this->sendNetPacket(std::move(lpPacket));
65 }
66 
67 void
68 GenericLinkService::doSendData(const Data& data)
69 {
70  lp::Packet lpPacket(data.wireEncode());
71 
72  if (m_options.allowLocalFields) {
73  encodeLocalFields(data, lpPacket);
74  }
75 
76  this->sendNetPacket(std::move(lpPacket));
77 }
78 
79 void
80 GenericLinkService::doSendNack(const lp::Nack& nack)
81 {
82  lp::Packet lpPacket(nack.getInterest().wireEncode());
83  lpPacket.add<lp::NackField>(nack.getHeader());
84 
85  if (m_options.allowLocalFields) {
86  encodeLocalFields(nack, lpPacket);
87  }
88 
89  this->sendNetPacket(std::move(lpPacket));
90 }
91 
92 void
93 GenericLinkService::encodeLocalFields(const ndn::TagHost& netPkt, lp::Packet& lpPacket)
94 {
95  shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = netPkt.getTag<lp::IncomingFaceIdTag>();
96  if (incomingFaceIdTag != nullptr) {
97  lpPacket.add<lp::IncomingFaceIdField>(*incomingFaceIdTag);
98  }
99 }
100 
101 void
102 GenericLinkService::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)
111  ++this->nFragmentationErrors;
112  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
121  this->assignSequences(frags);
122  }
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)) {
134  ++this->nOutOverMtu;
135  NFD_LOG_FACE_WARN("attempt to send packet over MTU limit");
136  continue;
137  }
138  this->sendPacket(std::move(tp));
139  }
140 }
141 
142 void
143 GenericLinkService::assignSequence(lp::Packet& pkt)
144 {
145  pkt.set<lp::SequenceField>(++m_lastSeqNo);
146 }
147 
148 void
149 GenericLinkService::assignSequences(std::vector<lp::Packet>& pkts)
150 {
151  std::for_each(pkts.begin(), pkts.end(), bind(&GenericLinkService::assignSequence, this, _1));
152 }
153 
154 void
155 GenericLinkService::doReceivePacket(Transport::Packet&& packet)
156 {
157  try {
158  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 
165  if ((pkt.has<lp::FragIndexField>() || pkt.has<lp::FragCountField>()) &&
166  !m_options.allowReassembly) {
167  NFD_LOG_FACE_WARN("received fragment, but reassembly disabled: DROP");
168  return;
169  }
170 
171  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 }
185 
186 void
187 GenericLinkService::decodeNetPacket(const Block& netPkt, const lp::Packet& firstPkt)
188 {
189  try {
190  switch (netPkt.type()) {
191  case tlv::Interest:
192  if (firstPkt.has<lp::NackField>()) {
193  this->decodeNack(netPkt, firstPkt);
194  }
195  else {
196  this->decodeInterest(netPkt, firstPkt);
197  }
198  break;
199  case tlv::Data:
200  this->decodeData(netPkt, firstPkt);
201  break;
202  default:
203  ++this->nInNetInvalid;
204  NFD_LOG_FACE_WARN("unrecognized network-layer packet TLV-TYPE " << netPkt.type() << ": DROP");
205  return;
206  }
207  }
208  catch (const tlv::Error& e) {
209  ++this->nInNetInvalid;
210  NFD_LOG_FACE_WARN("packet parse error (" << e.what() << "): DROP");
211  }
212 }
213 
214 void
215 GenericLinkService::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) {
225  interest->setTag(make_shared<lp::NextHopFaceIdTag>(firstPkt.get<lp::NextHopFaceIdField>()));
226  }
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>()) {
234  ++this->nInNetInvalid;
235  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 
246 void
247 GenericLinkService::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>()) {
255  ++this->nInNetInvalid;
256  NFD_LOG_FACE_WARN("received Nack with Data: DROP");
257  return;
258  }
259 
260  if (firstPkt.has<lp::NextHopFaceIdField>()) {
261  ++this->nInNetInvalid;
262  NFD_LOG_FACE_WARN("received NextHopFaceId with Data: DROP");
263  return;
264  }
265 
266  if (firstPkt.has<lp::CachePolicyField>()) {
267  if (m_options.allowLocalFields) {
268  // 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>()));
271  }
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 
284 void
285 GenericLinkService::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>()) {
294  ++this->nInNetInvalid;
295  NFD_LOG_FACE_WARN("received NextHopFaceId with Nack: DROP");
296  return;
297  }
298 
299  if (firstPkt.has<lp::CachePolicyField>()) {
300  ++this->nInNetInvalid;
301  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);
310 }
311 
312 } // namespace face
313 } // namespace nfd
LpFragmenter::Options fragmenterOptions
options for fragmentation
void setTag(shared_ptr< T > tag) const
set a tag item
Definition: tag-host.hpp:80
signal::Signal< LpReassembler, Transport::EndpointId, size_t > beforeTimeout
signals before a partial packet is dropped due to timeout
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:67
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
Definition: face-log.hpp:74
bool allowLocalFields
enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy ...
Packet & set(const typename FIELD::ValueType &value)
remove all occurrences of FIELD, and add a FIELD with value
Definition: packet.hpp:144
const ssize_t MTU_UNLIMITED
indicates the transport has no limit on payload size
Definition: transport.hpp:95
Base class to store tag information (e.g., inside Interest and Data packets)
Definition: tag-host.hpp:34
Packet & add(const typename FIELD::ValueType &value)
add a FIELD with value
Definition: packet.hpp:156
Nack & setHeader(const NackHeader &header)
Definition: nack.hpp:77
const Transport * getTransport() const
stores a packet along with the remote endpoint
Definition: transport.hpp:113
PacketCounter nReassemblyTimeouts
count of dropped partial network-layer packets due to reassembly timeout
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
const NackHeader & getHeader() const
Definition: nack.hpp:65
void sendPacket(Transport::Packet &&packet)
sends a lower-layer packet via Transport
bool has() const
Definition: packet.hpp:75
GenericLinkServiceCounters(const LpReassembler &reassembler)
represents a Network Nack
Definition: nack.hpp:40
provides a tag type for simple types
Definition: tag.hpp:58
FIELD::ValueType get(size_t index=0) const
Definition: packet.hpp:100
PacketCounter nOutOverMtu
count of outgoing LpPackets dropped due to exceeding MTU limit
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
void receiveNack(const lp::Nack &nack)
delivers received Nack to forwarding
ssize_t getMtu() const
Definition: transport.hpp:410
reassembles fragmented network-layer packets
counters provided by GenericLinkService
Options that control the behavior of GenericLinkService.
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: interest.cpp:217
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
void receiveData(const Data &data)
delivers received Data to forwarding
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
std::tuple< bool, Block, lp::Packet > receiveFragment(Transport::EndpointId remoteEndpoint, const lp::Packet &packet)
adds received fragment to buffer
PacketCounter nInNetInvalid
count of invalid reassembled network-layer packets dropped
std::tuple< bool, std::vector< lp::Packet > > fragmentPacket(const lp::Packet &packet, size_t mtu)
fragments a network-layer packet into link-layer packets
LpReassembler::Options reassemblerOptions
options for reassembly
represents a Data packet
Definition: data.hpp:39
GenericLinkService(const Options &options=Options())
uint32_t type() const
Definition: block.hpp:346
const Interest & getInterest() const
Definition: nack.hpp:53
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
Definition: face-log.hpp:83
PacketCounter nInLpInvalid
count of invalid LpPackets dropped before reassembly
void receiveInterest(const Interest &interest)
delivers received Interest to forwarding
PacketCounter nFragmentationErrors
count of failed fragmentations
bool allowFragmentation
enables fragmentation