blob: 3d6f3def8dd0af8854c6736ec7bb6364a8078228 [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"
31
32#include "ns3/assert.h"
33#include "ns3/ptr.h"
34#include "ns3/log.h"
35#include "ns3/simulator.h"
36#include "ns3/boolean.h"
37#include "ns3/string.h"
38
39#include <boost/ref.hpp>
40#include <boost/foreach.hpp>
41#include <boost/lambda/lambda.hpp>
42#include <boost/lambda/bind.hpp>
43#include <boost/tuple/tuple.hpp>
44namespace ll = boost::lambda;
45
46NS_LOG_COMPONENT_DEFINE ("CcnxForwardingStrategy");
47
48namespace ns3 {
49
50using namespace __ccnx_private;
51
52NS_OBJECT_ENSURE_REGISTERED (CcnxForwardingStrategy);
53
54TypeId CcnxForwardingStrategy::GetTypeId (void)
55{
56 static TypeId tid = TypeId ("ns3::CcnxForwardingStrategy")
57 .SetGroupName ("Ccnx")
58 .SetParent<Object> ()
59
60 ////////////////////////////////////////////////////////////////////
61 ////////////////////////////////////////////////////////////////////
62
63 .AddTraceSource ("OutInterests", "OutInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_outInterests))
64 .AddTraceSource ("InInterests", "InInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_inInterests))
65 .AddTraceSource ("DropInterests", "DropInterests", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_dropInterests))
66
67 ////////////////////////////////////////////////////////////////////
68 ////////////////////////////////////////////////////////////////////
69
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070070 .AddTraceSource ("OutData", "OutData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_outData))
71 .AddTraceSource ("InData", "InData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_inData))
72 .AddTraceSource ("DropData", "DropData", MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_dropData))
73
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070074 .AddAttribute ("CacheUnsolicitedData", "Cache overheard data that have not been requested",
75 BooleanValue (false),
76 MakeBooleanAccessor (&CcnxForwardingStrategy::m_cacheUnsolicitedData),
77 MakeBooleanChecker ())
78
Alexander Afanasyev996b4872012-07-17 17:07:56 -070079 .AddAttribute ("DetectRetransmissions", "If non-duplicate interest is received on the same face more than once, "
80 "it is considered a retransmission",
81 BooleanValue (true),
82 MakeBooleanAccessor (&CcnxForwardingStrategy::m_detectRetransmissions),
83 MakeBooleanChecker ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070084 ;
85 return tid;
86}
87
88CcnxForwardingStrategy::CcnxForwardingStrategy ()
89{
90}
91
92CcnxForwardingStrategy::~CcnxForwardingStrategy ()
93{
94}
95
96void
97CcnxForwardingStrategy::NotifyNewAggregate ()
98{
99 if (m_pit == 0)
100 {
101 m_pit = GetObject<CcnxPit> ();
102 }
103 if (m_fib == 0)
104 {
105 m_fib = GetObject<CcnxFib> ();
106 }
107 if (m_contentStore == 0)
108 {
109 m_contentStore = GetObject<CcnxContentStore> ();
110 }
111
112 Object::NotifyNewAggregate ();
113}
114
115void
116CcnxForwardingStrategy::DoDispose ()
117{
118 m_pit = 0;
119 m_contentStore = 0;
120 m_fib = 0;
121
122 Object::DoDispose ();
123}
124
125void
126CcnxForwardingStrategy::OnInterest (const Ptr<CcnxFace> &incomingFace,
127 Ptr<CcnxInterestHeader> &header,
128 const Ptr<const Packet> &packet)
129{
130 m_inInterests (header, incomingFace);
131
132 Ptr<CcnxPitEntry> pitEntry = m_pit->Lookup (*header);
133 if (pitEntry == 0)
134 {
135 pitEntry = m_pit->Create (header);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700136 if (pitEntry != 0)
137 {
138 DidCreatePitEntry (incomingFace, header, packet, pitEntry);
139 }
140 else
141 {
142 FailedToCreatePitEntry (incomingFace, header, packet);
143 return;
144 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700145 }
146
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700147 bool isDuplicated = true;
148 if (!pitEntry->IsNonceSeen (header->GetNonce ()))
149 {
150 pitEntry->AddSeenNonce (header->GetNonce ());
151 isDuplicated = false;
152 }
153
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700154 if (isDuplicated)
155 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700156 DidReceiveDuplicateInterest (incomingFace, header, packet, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700157 return;
158 }
159
160 Ptr<Packet> contentObject;
161 Ptr<const CcnxContentObjectHeader> contentObjectHeader; // used for tracing
162 Ptr<const Packet> payload; // used for tracing
163 boost::tie (contentObject, contentObjectHeader, payload) = m_contentStore->Lookup (header);
164 if (contentObject != 0)
165 {
166 NS_ASSERT (contentObjectHeader != 0);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700167
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700168 pitEntry->AddIncoming (incomingFace/*, Seconds (1.0)*/);
169 SatisfyPendingInterest (0, contentObjectHeader, payload, contentObject, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700170 return;
171 }
172
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700173 if (ShouldSuppressIncomingInterest (incomingFace, pitEntry))
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700174 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700175 pitEntry->AddIncoming (incomingFace/*, header->GetInterestLifetime ()*/);
176 // update PIT entry lifetime
177 pitEntry->UpdateLifetime (header->GetInterestLifetime ());
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700178
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700179 // Suppress this interest if we're still expecting data from some other face
180 NS_LOG_DEBUG ("Suppress interests");
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700181 m_dropInterests (header, incomingFace);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700182 return;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700183 }
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700184
185 PropagateInterest (incomingFace, header, packet, pitEntry);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700186}
187
188void
189CcnxForwardingStrategy::OnData (const Ptr<CcnxFace> &incomingFace,
190 Ptr<CcnxContentObjectHeader> &header,
191 Ptr<Packet> &payload,
192 const Ptr<const Packet> &packet)
193{
194 NS_LOG_FUNCTION (incomingFace << header->GetName () << payload << packet);
195 m_inData (header, payload, incomingFace);
196
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700197 // Lookup PIT entry
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700198 Ptr<CcnxPitEntry> pitEntry = m_pit->Lookup (*header);
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700199 if (pitEntry == 0)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700200 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700201 DidReceiveUnsolicitedData (incomingFace, header, payload);
202 return;
203 }
204 else
205 {
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700206 // Add or update entry in the content store
207 m_contentStore->Add (header, payload);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700208 }
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700209
210 while (pitEntry != 0)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700211 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700212 // Do data plane performance measurements
213 WillSatisfyPendingInterest (incomingFace, pitEntry);
214
215 // Actually satisfy pending interest
216 SatisfyPendingInterest (incomingFace, header, payload, packet, pitEntry);
217
218 // Lookup another PIT entry
219 pitEntry = m_pit->Lookup (*header);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700220 }
221}
222
223
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700224void
225CcnxForwardingStrategy::DidReceiveDuplicateInterest (const Ptr<CcnxFace> &incomingFace,
226 Ptr<CcnxInterestHeader> &header,
227 const Ptr<const Packet> &packet,
228 Ptr<CcnxPitEntry> pitEntry)
229{
230 NS_LOG_FUNCTION (this << *incomingFace);
231 /////////////////////////////////////////////////////////////////////////////////////////
232 // //
233 // !!!! IMPORTANT CHANGE !!!! Duplicate interests will create incoming face entry !!!! //
234 // //
235 /////////////////////////////////////////////////////////////////////////////////////////
236 pitEntry->AddIncoming (incomingFace);
237 m_dropInterests (header, incomingFace);
238}
239
240void
241CcnxForwardingStrategy::DidExhaustForwardingOptions (const Ptr<CcnxFace> &incomingFace,
242 Ptr<CcnxInterestHeader> header,
243 const Ptr<const Packet> &packet,
244 Ptr<CcnxPitEntry> pitEntry)
245{
246 NS_LOG_FUNCTION (this << *incomingFace);
247 m_dropInterests (header, incomingFace);
248}
249
250void
251CcnxForwardingStrategy::FailedToCreatePitEntry (const Ptr<CcnxFace> &incomingFace,
252 Ptr<CcnxInterestHeader> header,
253 const Ptr<const Packet> &packet)
254{
255 NS_LOG_FUNCTION (this);
256 m_dropInterests (header, incomingFace);
257}
258
259void
260CcnxForwardingStrategy::DidCreatePitEntry (const Ptr<CcnxFace> &incomingFace,
261 Ptr<CcnxInterestHeader> header,
262 const Ptr<const Packet> &packet,
263 Ptr<CcnxPitEntry> pitEntrypitEntry)
264{
265}
266
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700267bool
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700268CcnxForwardingStrategy::DetectRetransmittedInterest (const Ptr<CcnxFace> &incomingFace,
269 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700270{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700271 CcnxPitEntry::in_iterator inFace = pitEntry->GetIncoming ().find (incomingFace);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700272
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700273 bool isRetransmitted = false;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700274
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700275 if (inFace != pitEntry->GetIncoming ().end ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700276 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700277 // this is almost definitely a retransmission. But should we trust the user on that?
278 isRetransmitted = true;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700279 }
280
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700281 return isRetransmitted;
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700282}
283
284void
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700285CcnxForwardingStrategy::SatisfyPendingInterest (const Ptr<CcnxFace> &incomingFace,
286 Ptr<const CcnxContentObjectHeader> header,
287 Ptr<const Packet> payload,
288 const Ptr<const Packet> &packet,
289 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700290{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700291 if (incomingFace != 0)
292 pitEntry->RemoveIncoming (incomingFace);
293
294 //satisfy all pending incoming Interests
295 BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry->GetIncoming ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700296 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700297 incoming.m_face->Send (packet->Copy ());
298 m_outData (header, payload, false, incoming.m_face);
299 NS_LOG_DEBUG ("Satisfy " << *incoming.m_face);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700300
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700301 // successfull forwarded data trace
302 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700303
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700304 // All incoming interests are satisfied. Remove them
305 pitEntry->ClearIncoming ();
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700306
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700307 // Remove all outgoing faces
308 pitEntry->ClearOutgoing ();
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700309
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700310 // Set pruning timout on PIT entry (instead of deleting the record)
311 m_pit->MarkErased (pitEntry);
312}
313
314void
315CcnxForwardingStrategy::DidReceiveUnsolicitedData (const Ptr<CcnxFace> &incomingFace,
316 Ptr<const CcnxContentObjectHeader> header,
317 Ptr<const Packet> payload)
318{
319 if (m_cacheUnsolicitedData)
320 {
321 // Optimistically add or update entry in the content store
322 m_contentStore->Add (header, payload);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700323 }
324 else
325 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700326 // Drop data packet if PIT entry is not found
327 // (unsolicited data packets should not "poison" content store)
328
329 //drop dulicated or not requested data packet
330 m_dropData (header, payload, incomingFace);
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700331 }
332}
333
334void
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700335CcnxForwardingStrategy::WillSatisfyPendingInterest (const Ptr<CcnxFace> &incomingFace,
336 Ptr<CcnxPitEntry> pitEntry)
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700337{
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700338 CcnxPitEntry::out_iterator out = pitEntry->GetOutgoing ().find (incomingFace);
339
340 // If we have sent interest for this data via this face, then update stats.
341 if (out != pitEntry->GetOutgoing ().end ())
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700342 {
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700343 pitEntry->GetFibEntry ()->UpdateFaceRtt (incomingFace, Simulator::Now () - out->m_sendTime);
344 }
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700345}
346
Alexander Afanasyev996b4872012-07-17 17:07:56 -0700347bool
348CcnxForwardingStrategy::ShouldSuppressIncomingInterest (const Ptr<CcnxFace> &incomingFace,
349 Ptr<CcnxPitEntry> pitEntry)
350{
351 bool isNew = pitEntry->GetIncoming ().size () == 0 && pitEntry->GetOutgoing ().size () == 0;
352
353 if (isNew) return false; // never suppress new interests
354
355 bool isRetransmitted = m_detectRetransmissions && // a small guard
356 DetectRetransmittedInterest (incomingFace, pitEntry);
357
358 if (pitEntry->GetOutgoing ().find (incomingFace) != pitEntry->GetOutgoing ().end ())
359 {
360 NS_LOG_DEBUG ("Non duplicate interests from the face we have sent interest to. Don't suppress");
361 // got a non-duplicate interest from the face we have sent interest to
362 // Probably, there is no point in waiting data from that face... Not sure yet
363
364 // If we're expecting data from the interface we got the interest from ("producer" asks us for "his own" data)
365 // Mark interface YELLOW, but keep a small hope that data will come eventually.
366
367 // ?? not sure if we need to do that ?? ...
368
369 // pitEntry->GetFibEntry ()->UpdateStatus (incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW);
370 }
371 else
372 if (!isNew && !isRetransmitted)
373 {
374 return true;
375 }
376
377 return false;
378}
379
380void
381CcnxForwardingStrategy::PropagateInterest (const Ptr<CcnxFace> &incomingFace,
382 Ptr<CcnxInterestHeader> &header,
383 const Ptr<const Packet> &packet,
384 Ptr<CcnxPitEntry> pitEntry)
385{
386 bool isRetransmitted = m_detectRetransmissions && // a small guard
387 DetectRetransmittedInterest (incomingFace, pitEntry);
388
389 pitEntry->AddIncoming (incomingFace/*, header->GetInterestLifetime ()*/);
390 /// @todo Make lifetime per incoming interface
391 pitEntry->UpdateLifetime (header->GetInterestLifetime ());
392
393 bool propagated = DoPropagateInterest (incomingFace, header, packet, pitEntry);
394
395 if (!propagated && isRetransmitted) //give another chance if retransmitted
396 {
397 // increase max number of allowed retransmissions
398 pitEntry->IncreaseAllowedRetxCount ();
399
400 // try again
401 propagated = DoPropagateInterest (incomingFace, header, packet, pitEntry);
402 }
403
404 // ForwardingStrategy will try its best to forward packet to at least one interface.
405 // If no interests was propagated, then there is not other option for forwarding or
406 // ForwardingStrategy failed to find it.
407 if (!propagated && pitEntry->GetOutgoing ().size () == 0)
408 {
409 DidExhaustForwardingOptions (incomingFace, header, packet, pitEntry);
410 }
411}
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -0700412
413} //namespace ns3