blob: ddc4e51ec6d7ef7de802594cf8d69ff830063e92 [file] [log] [blame]
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2011 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 * Ilya Moiseenko <iliamo@cs.ucla.edu>
20 */
21
22#include "ccnx-forwarding-strategy.h"
23
24#include "ns3/ccnx-pit.h"
25#include "ns3/ccnx-pit-entry.h"
26#include "ns3/ccnx-interest-header.h"
27#include "ns3/ccnx-content-object-header.h"
28#include "ns3/ccnx-pit.h"
29#include "ns3/ccnx-fib.h"
30#include "ns3/ccnx-content-store.h"
Alexander Afanasyevf249a192012-07-18 16:52:51 -070031#include "ns3/ccnx-face.h"
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070032
33#include "ns3/assert.h"
34#include "ns3/ptr.h"
35#include "ns3/log.h"
36#include "ns3/simulator.h"
37#include "ns3/boolean.h"
38#include "ns3/string.h"
39
40#include <boost/ref.hpp>
41#include <boost/foreach.hpp>
42#include <boost/lambda/lambda.hpp>
43#include <boost/lambda/bind.hpp>
44#include <boost/tuple/tuple.hpp>
45namespace ll = boost::lambda;
46
47NS_LOG_COMPONENT_DEFINE ("CcnxForwardingStrategy");
48
49namespace ns3 {
50
51using namespace __ccnx_private;
52
53NS_OBJECT_ENSURE_REGISTERED (CcnxForwardingStrategy);
54
55TypeId CcnxForwardingStrategy::GetTypeId (void)
56{
57 static TypeId tid = TypeId ("ns3::CcnxForwardingStrategy")
58 .SetGroupName ("Ccnx")
59 .SetParent<Object> ()
60
61 ////////////////////////////////////////////////////////////////////
62 ////////////////////////////////////////////////////////////////////
63
64 .AddTraceSource ("OutInterests", "OutInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_outInterests))
65 .AddTraceSource ("InInterests", "InInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_inInterests))
66 .AddTraceSource ("DropInterests", "DropInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_dropInterests))
67
68 ////////////////////////////////////////////////////////////////////
69 ////////////////////////////////////////////////////////////////////
70
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070071 .AddTraceSource ("OutData", "OutData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_outData))
72 .AddTraceSource ("InData", "InData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_inData))
73 .AddTraceSource ("DropData", "DropData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_dropData))
74
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070075 .AddAttribute ("CacheUnsolicitedData", "Cache overheard data that have not been requested",
76 BooleanValue (false),
77 MakeBooleanAccessor (&CcnxForwardingStrategy::m_cacheUnsolicitedData),
78 MakeBooleanChecker ())
79
Alexander Afanasyev996b4872012-07-17 17:07:56 -070080 .AddAttribute ("DetectRetransmissions", "If non-duplicate interest is received on the same face more than once, "
81 "it is considered a retransmission",
82 BooleanValue (true),
83 MakeBooleanAccessor (&CcnxForwardingStrategy::m_detectRetransmissions),
84 MakeBooleanChecker ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070085 ;
86 return tid;
87}
88
89CcnxForwardingStrategy::CcnxForwardingStrategy ()
90{
91}
92
93CcnxForwardingStrategy::~CcnxForwardingStrategy ()
94{
95}
96
97void
98CcnxForwardingStrategy::NotifyNewAggregate ()
99{
100 if (m_pit == 0)
101 {
102 m_pit = GetObject<CcnxPit> ();
103 }
104 if (m_fib == 0)
105 {
106 m_fib = GetObject<CcnxFib> ();
107 }
108 if (m_contentStore == 0)
109 {
110 m_contentStore = GetObject<CcnxContentStore> ();
111 }
112
113 Object::NotifyNewAggregate ();
114}
115
116void
117CcnxForwardingStrategy::DoDispose ()
118{
119 m_pit = 0;
120 m_contentStore = 0;
121 m_fib = 0;
122
123 Object::DoDispose ();
124}
125
126void
127CcnxForwardingStrategy::OnInterest (const Ptr<CcnxFace> &incomingFace,
128 Ptr<CcnxInterestHeader> &header,
129 const Ptr<const Packet> &packet)
130{
131 m_inInterests (header, incomingFace);
132
133 Ptr<CcnxPitEntry> pitEntry = m_pit->Lookup (*header);
134 if (pitEntry == 0)
135 {
136 pitEntry = m_pit->Create (header);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700137 if (pitEntry != 0)
138 {
139 DidCreatePitEntry (incomingFace, header, packet, pitEntry);
140 }
141 else
142 {
143 FailedToCreatePitEntry (incomingFace, header, packet);
144 return;
145 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700146 }
147
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700148 bool isDuplicated = true;
149 if (!pitEntry->IsNonceSeen (header->GetNonce ()))
150 {
151 pitEntry->AddSeenNonce (header->GetNonce ());
152 isDuplicated = false;
153 }
154
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700155 if (isDuplicated)
156 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700157 DidReceiveDuplicateInterest (incomingFace, header, packet, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700158 return;
159 }
160
161 Ptr<Packet> contentObject;
162 Ptr<const CcnxContentObjectHeader> contentObjectHeader; // used for tracing
163 Ptr<const Packet> payload; // used for tracing
164 boost::tie (contentObject, contentObjectHeader, payload) = m_contentStore->Lookup (header);
165 if (contentObject != 0)
166 {
167 NS_ASSERT (contentObjectHeader != 0);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700168
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700169 pitEntry->AddIncoming (incomingFace/*, Seconds (1.0)*/);
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700170
171 // Do data plane performance measurements
172 WillSatisfyPendingInterest (0, pitEntry);
173
174 // Actually satisfy pending interest
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700175 SatisfyPendingInterest (0, contentObjectHeader, payload, contentObject, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700176 return;
177 }
178
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700179 if (ShouldSuppressIncomingInterest (incomingFace, pitEntry))
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700180 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700181 pitEntry->AddIncoming (incomingFace/*, header->GetInterestLifetime ()*/);
182 // update PIT entry lifetime
183 pitEntry->UpdateLifetime (header->GetInterestLifetime ());
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700184
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700185 // Suppress this interest if we're still expecting data from some other face
186 NS_LOG_DEBUG ("Suppress interests");
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700187 m_dropInterests (header, incomingFace);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700188 return;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700189 }
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700190
191 PropagateInterest (incomingFace, header, packet, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700192}
193
194void
195CcnxForwardingStrategy::OnData (const Ptr<CcnxFace> &incomingFace,
196 Ptr<CcnxContentObjectHeader> &header,
197 Ptr<Packet> &payload,
198 const Ptr<const Packet> &packet)
199{
200 NS_LOG_FUNCTION (incomingFace << header->GetName () << payload << packet);
201 m_inData (header, payload, incomingFace);
202
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700203 // Lookup PIT entry
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700204 Ptr<CcnxPitEntry> pitEntry = m_pit->Lookup (*header);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700205 if (pitEntry == 0)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700206 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700207 DidReceiveUnsolicitedData (incomingFace, header, payload);
208 return;
209 }
210 else
211 {
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700212 // Add or update entry in the content store
213 m_contentStore->Add (header, payload);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700214 }
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700215
216 while (pitEntry != 0)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700217 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700218 // Do data plane performance measurements
219 WillSatisfyPendingInterest (incomingFace, pitEntry);
220
221 // Actually satisfy pending interest
222 SatisfyPendingInterest (incomingFace, header, payload, packet, pitEntry);
223
224 // Lookup another PIT entry
225 pitEntry = m_pit->Lookup (*header);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700226 }
227}
228
229
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700230void
231CcnxForwardingStrategy::DidReceiveDuplicateInterest (const Ptr<CcnxFace> &incomingFace,
232 Ptr<CcnxInterestHeader> &header,
233 const Ptr<const Packet> &packet,
234 Ptr<CcnxPitEntry> pitEntry)
235{
Alexander Afanasyeve288d8b2012-07-20 15:35:17 -0700236 NS_LOG_FUNCTION (this << boost::cref (*incomingFace));
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700237 /////////////////////////////////////////////////////////////////////////////////////////
238 // //
239 // !!!! IMPORTANT CHANGE !!!! Duplicate interests will create incoming face entry !!!! //
240 // //
241 /////////////////////////////////////////////////////////////////////////////////////////
242 pitEntry->AddIncoming (incomingFace);
243 m_dropInterests (header, incomingFace);
244}
245
246void
247CcnxForwardingStrategy::DidExhaustForwardingOptions (const Ptr<CcnxFace> &incomingFace,
248 Ptr<CcnxInterestHeader> header,
249 const Ptr<const Packet> &packet,
250 Ptr<CcnxPitEntry> pitEntry)
251{
Alexander Afanasyeve288d8b2012-07-20 15:35:17 -0700252 NS_LOG_FUNCTION (this << boost::cref (*incomingFace));
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700253 m_dropInterests (header, incomingFace);
254}
255
256void
257CcnxForwardingStrategy::FailedToCreatePitEntry (const Ptr<CcnxFace> &incomingFace,
258 Ptr<CcnxInterestHeader> header,
259 const Ptr<const Packet> &packet)
260{
261 NS_LOG_FUNCTION (this);
262 m_dropInterests (header, incomingFace);
263}
264
265void
266CcnxForwardingStrategy::DidCreatePitEntry (const Ptr<CcnxFace> &incomingFace,
267 Ptr<CcnxInterestHeader> header,
268 const Ptr<const Packet> &packet,
269 Ptr<CcnxPitEntry> pitEntrypitEntry)
270{
271}
272
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700273bool
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700274CcnxForwardingStrategy::DetectRetransmittedInterest (const Ptr<CcnxFace> &incomingFace,
275 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700276{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700277 CcnxPitEntry::in_iterator inFace = pitEntry->GetIncoming ().find (incomingFace);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700278
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700279 bool isRetransmitted = false;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700280
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700281 if (inFace != pitEntry->GetIncoming ().end ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700282 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700283 // this is almost definitely a retransmission. But should we trust the user on that?
284 isRetransmitted = true;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700285 }
286
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700287 return isRetransmitted;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700288}
289
290void
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700291CcnxForwardingStrategy::SatisfyPendingInterest (const Ptr<CcnxFace> &incomingFace,
292 Ptr<const CcnxContentObjectHeader> header,
293 Ptr<const Packet> payload,
294 const Ptr<const Packet> &packet,
295 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700296{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700297 if (incomingFace != 0)
298 pitEntry->RemoveIncoming (incomingFace);
299
300 //satisfy all pending incoming Interests
301 BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry->GetIncoming ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700302 {
Alexander Afanasyev1c0248b2012-07-24 15:59:50 -0700303 bool ok = incoming.m_face->Send (packet->Copy ());
304 if (ok)
305 {
306 m_outData (header, payload, incomingFace == 0, incoming.m_face);
307 DidSendOutData (incoming.m_face, header, payload, packet);
308
309 NS_LOG_DEBUG ("Satisfy " << *incoming.m_face);
310 }
311 else
312 {
313 m_dropData (header, payload, incoming.m_face);
314 NS_LOG_DEBUG ("Cannot satisfy data to " << *incoming.m_face);
315 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700316
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700317 // successfull forwarded data trace
318 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700319
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700320 // All incoming interests are satisfied. Remove them
321 pitEntry->ClearIncoming ();
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700322
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700323 // Remove all outgoing faces
324 pitEntry->ClearOutgoing ();
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700325
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700326 // Set pruning timout on PIT entry (instead of deleting the record)
327 m_pit->MarkErased (pitEntry);
328}
329
330void
331CcnxForwardingStrategy::DidReceiveUnsolicitedData (const Ptr<CcnxFace> &incomingFace,
332 Ptr<const CcnxContentObjectHeader> header,
333 Ptr<const Packet> payload)
334{
335 if (m_cacheUnsolicitedData)
336 {
337 // Optimistically add or update entry in the content store
338 m_contentStore->Add (header, payload);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700339 }
340 else
341 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700342 // Drop data packet if PIT entry is not found
343 // (unsolicited data packets should not "poison" content store)
344
345 //drop dulicated or not requested data packet
346 m_dropData (header, payload, incomingFace);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700347 }
348}
349
350void
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700351CcnxForwardingStrategy::WillSatisfyPendingInterest (const Ptr<CcnxFace> &incomingFace,
352 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700353{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700354 CcnxPitEntry::out_iterator out = pitEntry->GetOutgoing ().find (incomingFace);
355
356 // If we have sent interest for this data via this face, then update stats.
357 if (out != pitEntry->GetOutgoing ().end ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700358 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700359 pitEntry->GetFibEntry ()->UpdateFaceRtt (incomingFace, Simulator::Now () - out->m_sendTime);
360 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700361}
362
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700363bool
364CcnxForwardingStrategy::ShouldSuppressIncomingInterest (const Ptr<CcnxFace> &incomingFace,
365 Ptr<CcnxPitEntry> pitEntry)
366{
367 bool isNew = pitEntry->GetIncoming ().size () == 0 && pitEntry->GetOutgoing ().size () == 0;
368
369 if (isNew) return false; // never suppress new interests
370
371 bool isRetransmitted = m_detectRetransmissions && // a small guard
372 DetectRetransmittedInterest (incomingFace, pitEntry);
373
374 if (pitEntry->GetOutgoing ().find (incomingFace) != pitEntry->GetOutgoing ().end ())
375 {
376 NS_LOG_DEBUG ("Non duplicate interests from the face we have sent interest to. Don't suppress");
377 // got a non-duplicate interest from the face we have sent interest to
378 // Probably, there is no point in waiting data from that face... Not sure yet
379
380 // If we're expecting data from the interface we got the interest from ("producer" asks us for "his own" data)
381 // Mark interface YELLOW, but keep a small hope that data will come eventually.
382
383 // ?? not sure if we need to do that ?? ...
384
385 // pitEntry->GetFibEntry ()->UpdateStatus (incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW);
386 }
387 else
388 if (!isNew && !isRetransmitted)
389 {
390 return true;
391 }
392
393 return false;
394}
395
396void
397CcnxForwardingStrategy::PropagateInterest (const Ptr<CcnxFace> &incomingFace,
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700398 Ptr<CcnxInterestHeader> header,
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700399 const Ptr<const Packet> &packet,
400 Ptr<CcnxPitEntry> pitEntry)
401{
402 bool isRetransmitted = m_detectRetransmissions && // a small guard
403 DetectRetransmittedInterest (incomingFace, pitEntry);
404
405 pitEntry->AddIncoming (incomingFace/*, header->GetInterestLifetime ()*/);
406 /// @todo Make lifetime per incoming interface
407 pitEntry->UpdateLifetime (header->GetInterestLifetime ());
408
409 bool propagated = DoPropagateInterest (incomingFace, header, packet, pitEntry);
410
411 if (!propagated && isRetransmitted) //give another chance if retransmitted
412 {
413 // increase max number of allowed retransmissions
414 pitEntry->IncreaseAllowedRetxCount ();
415
416 // try again
417 propagated = DoPropagateInterest (incomingFace, header, packet, pitEntry);
418 }
419
420 // ForwardingStrategy will try its best to forward packet to at least one interface.
421 // If no interests was propagated, then there is not other option for forwarding or
422 // ForwardingStrategy failed to find it.
423 if (!propagated && pitEntry->GetOutgoing ().size () == 0)
424 {
425 DidExhaustForwardingOptions (incomingFace, header, packet, pitEntry);
426 }
427}
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700428
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700429bool
430CcnxForwardingStrategy::WillSendOutInterest (const Ptr<CcnxFace> &outgoingFace,
431 Ptr<CcnxInterestHeader> header,
432 Ptr<CcnxPitEntry> pitEntry)
433{
434 CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
435 pitEntry->GetOutgoing ().find (outgoingFace);
436
437 if (outgoing != pitEntry->GetOutgoing ().end () &&
438 outgoing->m_retxCount >= pitEntry->GetMaxRetxCount ())
439 {
440 NS_LOG_ERROR (outgoing->m_retxCount << " >= " << pitEntry->GetMaxRetxCount ());
441 return false; // already forwarded before during this retransmission cycle
442 }
443
444
445 bool ok = outgoingFace->IsBelowLimit ();
446 if (!ok)
447 return false;
448
449 pitEntry->AddOutgoing (outgoingFace);
450 return true;
451}
452
453void
454CcnxForwardingStrategy::DidSendOutInterest (const Ptr<CcnxFace> &outgoingFace,
455 Ptr<CcnxInterestHeader> header,
Alexander Afanasyev1c0248b2012-07-24 15:59:50 -0700456 const Ptr<const Packet> &packet,
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700457 Ptr<CcnxPitEntry> pitEntry)
458{
459 m_outInterests (header, outgoingFace);
460}
461
462void
Alexander Afanasyev1c0248b2012-07-24 15:59:50 -0700463CcnxForwardingStrategy::DidSendOutData (const Ptr<CcnxFace> &face,
464 Ptr<const CcnxContentObjectHeader> header,
465 Ptr<const Packet> payload,
466 const Ptr<const Packet> &packet)
467{
468}
469
470void
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700471CcnxForwardingStrategy::WillErasePendingInterest (Ptr<CcnxPitEntry> pitEntry)
472{
473 // do nothing for now. may be need to do some logging
474}
475
Alexander Afanasyev33364b62012-07-26 17:53:56 -0700476
477void
478CcnxForwardingStrategy::RemoveFace (Ptr<CcnxFace> face)
479{
480 // do nothing here
481}
482
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700483} //namespace ns3