blob: 024054ac1b55da86db8e04e05f416250cf79a0e1 [file] [log] [blame]
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -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 */
20
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070021#ifndef _NDN_PIT_IMPL_H_
22#define _NDN_PIT_IMPL_H_
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070023
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070024#include "ndn-pit.h"
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070025
Alexander Afanasyev26719e22013-03-26 12:43:28 -070026#include "ns3/log.h"
27#include "ns3/simulator.h"
Alexander Afanasyev413c7f12012-07-10 17:35:16 -070028
Alexander Afanasyev26719e22013-03-26 12:43:28 -070029#include "../../utils/trie/trie-with-policy.h"
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070030#include "ndn-pit-entry-impl.h"
Alexander Afanasyev413c7f12012-07-10 17:35:16 -070031
Alexander Afanasyev26719e22013-03-26 12:43:28 -070032#include "ns3/ndn-interest.h"
33#include "ns3/ndn-content-object.h"
34#include "ns3/ndn-forwarding-strategy.h"
Alexander Afanasyevcfdc14f2013-03-15 14:38:44 -070035#include "ns3/ndn-name.h"
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070036
Alexander Afanasyev26719e22013-03-26 12:43:28 -070037
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070038namespace ns3 {
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070039namespace ndn {
40
41class ForwardingStrategy;
42
43namespace pit {
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070044
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070045/**
Alexander Afanasyev4aac5572012-08-09 10:49:55 -070046 * \ingroup ndn
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070047 * \brief Class implementing Pending Interests Table
48 */
Alexander Afanasyevbd6f3f42012-07-26 17:50:17 -070049template<class Policy>
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070050class PitImpl : public Pit
Alexander Afanasyevcfdc14f2013-03-15 14:38:44 -070051 , protected ndnSIM::trie_with_policy<Name,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070052 ndnSIM::smart_pointer_payload_traits< EntryImpl< PitImpl< Policy > > >,
53 // ndnSIM::persistent_policy_traits
54 Policy
55 >
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070056{
57public:
Alexander Afanasyevcfdc14f2013-03-15 14:38:44 -070058 typedef ndnSIM::trie_with_policy<Name,
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070059 ndnSIM::smart_pointer_payload_traits< EntryImpl< PitImpl< Policy > > >,
Alexander Afanasyevbd6f3f42012-07-26 17:50:17 -070060 // ndnSIM::persistent_policy_traits
61 Policy
Alexander Afanasyev36b45772012-07-10 16:57:42 -070062 > super;
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070063 typedef EntryImpl< PitImpl< Policy > > entry;
Alexander Afanasyev36b45772012-07-10 16:57:42 -070064
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070065 /**
66 * \brief Interface ID
67 *
68 * \return interface ID
69 */
70 static TypeId GetTypeId ();
71
72 /**
73 * \brief PIT constructor
74 */
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070075 PitImpl ();
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070076
77 /**
78 * \brief Destructor
79 */
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070080 virtual ~PitImpl ();
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070081
Alexander Afanasyev7456b702013-02-01 22:41:48 -080082 // inherited from Pit
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070083 virtual Ptr<Entry>
Alexander Afanasyeveae83ee2013-03-15 15:01:10 -070084 Lookup (const ContentObject &header);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070085
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070086 virtual Ptr<Entry>
Alexander Afanasyeveae83ee2013-03-15 15:01:10 -070087 Lookup (const Interest &header);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070088
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070089 virtual Ptr<Entry>
Alexander Afanasyeve5a8b5a2013-03-15 15:15:26 -070090 Find (const Name &prefix);
91
92 virtual Ptr<Entry>
Alexander Afanasyeveae83ee2013-03-15 15:01:10 -070093 Create (Ptr<const Interest> header);
Alexander Afanasyev7456b702013-02-01 22:41:48 -080094
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070095 virtual void
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070096 MarkErased (Ptr<Entry> entry);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070097
98 virtual void
99 Print (std::ostream &os) const;
Alexander Afanasyev1aa4bbc2012-07-09 17:17:25 -0700100
Alexander Afanasyevf1e013f2012-07-11 17:59:40 -0700101 virtual uint32_t
102 GetSize () const;
103
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700104 virtual Ptr<Entry>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700105 Begin ();
106
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700107 virtual Ptr<Entry>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700108 End ();
109
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700110 virtual Ptr<Entry>
111 Next (Ptr<Entry>);
Alexander Afanasyev7456b702013-02-01 22:41:48 -0800112
Alexander Afanasyev26719e22013-03-26 12:43:28 -0700113 const typename super::policy_container &
114 GetPolicy () const { return super::getPolicy (); }
115
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700116protected:
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700117 void RescheduleCleaning ();
118 void CleanExpired ();
Alexander Afanasyev7456b702013-02-01 22:41:48 -0800119
120 // inherited from Object class
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700121 virtual void NotifyNewAggregate (); ///< @brief Even when object is aggregated to another Object
122 virtual void DoDispose (); ///< @brief Do cleanup
123
124private:
125 uint32_t
126 GetMaxSize () const;
127
128 void
129 SetMaxSize (uint32_t maxSize);
Alexander Afanasyev7456b702013-02-01 22:41:48 -0800130
131 uint32_t
132 GetCurrentSize () const;
133
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700134private:
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700135 EventId m_cleanEvent;
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700136 Ptr<Fib> m_fib; ///< \brief Link to FIB table
137 Ptr<ForwardingStrategy> m_forwardingStrategy;
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700138
Alexander Afanasyev26719e22013-03-26 12:43:28 -0700139 static LogComponent g_log; ///< @brief Logging variable
140
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700141 // indexes
142 typedef
Alexander Afanasyev6b51b082012-07-27 16:28:34 -0700143 boost::intrusive::multiset<entry,
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700144 boost::intrusive::compare < TimestampIndex< entry > >,
145 boost::intrusive::member_hook< entry,
146 boost::intrusive::set_member_hook<>,
147 &entry::time_hook_>
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700148 > time_index;
Alexander Afanasyev7456b702013-02-01 22:41:48 -0800149 time_index i_time;
150
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700151 friend class EntryImpl< PitImpl >;
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700152};
153
Alexander Afanasyev26719e22013-03-26 12:43:28 -0700154//////////////////////////////////////////
155////////// Implementation ////////////////
156//////////////////////////////////////////
157
158template<class Policy>
159LogComponent PitImpl< Policy >::g_log = LogComponent (("ndn.pit." + Policy::GetName ()).c_str ());
160
161
162template<class Policy>
163TypeId
164PitImpl< Policy >::GetTypeId ()
165{
166 static TypeId tid = TypeId (("ns3::ndn::pit::"+Policy::GetName ()).c_str ())
167 .SetGroupName ("Ndn")
168 .SetParent<Pit> ()
169 .AddConstructor< PitImpl< Policy > > ()
170 .AddAttribute ("MaxSize",
171 "Set maximum size of PIT in bytes. If 0, limit is not enforced",
172 UintegerValue (0),
173 MakeUintegerAccessor (&PitImpl< Policy >::GetMaxSize,
174 &PitImpl< Policy >::SetMaxSize),
175 MakeUintegerChecker<uint32_t> ())
176
177 .AddAttribute ("CurrentSize", "Get current size of PIT in bytes",
178 TypeId::ATTR_GET,
179 UintegerValue (0),
180 MakeUintegerAccessor (&PitImpl< Policy >::GetCurrentSize),
181 MakeUintegerChecker<uint32_t> ())
182 ;
183
184 return tid;
185}
186
187template<class Policy>
188uint32_t
189PitImpl<Policy>::GetCurrentSize () const
190{
191 return super::getPolicy ().size ();
192}
193
194template<class Policy>
195PitImpl<Policy>::PitImpl ()
196{
197}
198
199template<class Policy>
200PitImpl<Policy>::~PitImpl ()
201{
202}
203
204template<class Policy>
205uint32_t
206PitImpl<Policy>::GetMaxSize () const
207{
208 return super::getPolicy ().get_max_size ();
209}
210
211template<class Policy>
212void
213PitImpl<Policy>::SetMaxSize (uint32_t maxSize)
214{
215 super::getPolicy ().set_max_size (maxSize);
216}
217
218template<class Policy>
219void
220PitImpl<Policy>::NotifyNewAggregate ()
221{
222 if (m_fib == 0)
223 {
224 m_fib = GetObject<Fib> ();
225 }
226 if (m_forwardingStrategy == 0)
227 {
228 m_forwardingStrategy = GetObject<ForwardingStrategy> ();
229 }
230
231 Pit::NotifyNewAggregate ();
232}
233
234template<class Policy>
235void
236PitImpl<Policy>::DoDispose ()
237{
238 super::clear ();
239
240 m_forwardingStrategy = 0;
241 m_fib = 0;
242
243 Pit::DoDispose ();
244}
245
246template<class Policy>
247void
248PitImpl<Policy>::RescheduleCleaning ()
249{
250 // m_cleanEvent.Cancel ();
251 Simulator::Remove (m_cleanEvent); // slower, but better for memory
252 if (i_time.empty ())
253 {
254 // NS_LOG_DEBUG ("No items in PIT");
255 return;
256 }
257
258 Time nextEvent = i_time.begin ()->GetExpireTime () - Simulator::Now ();
259 if (nextEvent <= 0) nextEvent = Seconds (0);
260
261 NS_LOG_DEBUG ("Schedule next cleaning in " <<
262 nextEvent.ToDouble (Time::S) << "s (at " <<
263 i_time.begin ()->GetExpireTime () << "s abs time");
264
265 m_cleanEvent = Simulator::Schedule (nextEvent,
266 &PitImpl<Policy>::CleanExpired, this);
267}
268
269template<class Policy>
270void
271PitImpl<Policy>::CleanExpired ()
272{
273 NS_LOG_LOGIC ("Cleaning PIT. Total: " << i_time.size ());
274 Time now = Simulator::Now ();
275
276 // uint32_t count = 0;
277 while (!i_time.empty ())
278 {
279 typename time_index::iterator entry = i_time.begin ();
280 if (entry->GetExpireTime () <= now) // is the record stale?
281 {
282 m_forwardingStrategy->WillEraseTimedOutPendingInterest (entry->to_iterator ()->payload ());
283 super::erase (entry->to_iterator ());
284 // count ++;
285 }
286 else
287 break; // nothing else to do. All later records will not be stale
288 }
289
290 if (super::getPolicy ().size ())
291 {
292 NS_LOG_DEBUG ("Size: " << super::getPolicy ().size ());
293 NS_LOG_DEBUG ("i_time size: " << i_time.size ());
294 }
295 RescheduleCleaning ();
296}
297
298template<class Policy>
299Ptr<Entry>
300PitImpl<Policy>::Lookup (const ContentObject &header)
301{
302 /// @todo use predicate to search with exclude filters
303 typename super::iterator item = super::longest_prefix_match_if (header.GetName (), EntryIsNotEmpty ());
304
305 if (item == super::end ())
306 return 0;
307 else
308 return item->payload (); // which could also be 0
309}
310
311template<class Policy>
312Ptr<Entry>
313PitImpl<Policy>::Lookup (const Interest &header)
314{
315 // NS_LOG_FUNCTION (header.GetName ());
316 NS_ASSERT_MSG (m_fib != 0, "FIB should be set");
317 NS_ASSERT_MSG (m_forwardingStrategy != 0, "Forwarding strategy should be set");
318
319 typename super::iterator foundItem, lastItem;
320 bool reachLast;
321 boost::tie (foundItem, reachLast, lastItem) = super::getTrie ().find (header.GetName ());
322
323 if (!reachLast || lastItem == super::end ())
324 return 0;
325 else
326 return lastItem->payload (); // which could also be 0
327}
328
329template<class Policy>
330Ptr<Entry>
331PitImpl<Policy>::Find (const Name &prefix)
332{
333 typename super::iterator item = super::find_exact (prefix);
334
335 if (item == super::end ())
336 return 0;
337 else
338 return item->payload ();
339}
340
341
342template<class Policy>
343Ptr<Entry>
344PitImpl<Policy>::Create (Ptr<const Interest> header)
345{
346 NS_LOG_DEBUG (header->GetName ());
347 Ptr<fib::Entry> fibEntry = m_fib->LongestPrefixMatch (*header);
348 if (fibEntry == 0)
349 return 0;
350
351 // NS_ASSERT_MSG (fibEntry != 0,
352 // "There should be at least default route set" <<
353 // " Prefix = "<< header->GetName() << ", NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
354
355 Ptr< entry > newEntry = ns3::Create< entry > (boost::ref (*this), header, fibEntry);
356 std::pair< typename super::iterator, bool > result = super::insert (header->GetName (), newEntry);
357 if (result.first != super::end ())
358 {
359 if (result.second)
360 {
361 newEntry->SetTrie (result.first);
362 return newEntry;
363 }
364 else
365 {
366 // should we do anything?
367 // update payload? add new payload?
368 return result.first->payload ();
369 }
370 }
371 else
372 return 0;
373}
374
375
376template<class Policy>
377void
378PitImpl<Policy>::MarkErased (Ptr<Entry> item)
379{
380 if (this->m_PitEntryPruningTimout.IsZero ())
381 {
382 super::erase (StaticCast< entry > (item)->to_iterator ());
383 }
384 else
385 {
386 item->OffsetLifetime (this->m_PitEntryPruningTimout - item->GetExpireTime () + Simulator::Now ());
387 }
388}
389
390
391template<class Policy>
392void
393PitImpl<Policy>::Print (std::ostream& os) const
394{
395 // !!! unordered_set imposes "random" order of item in the same level !!!
396 typename super::parent_trie::const_recursive_iterator item (super::getTrie ()), end (0);
397 for (; item != end; item++)
398 {
399 if (item->payload () == 0) continue;
400
401 os << item->payload ()->GetPrefix () << "\t" << *item->payload () << "\n";
402 }
403}
404
405template<class Policy>
406uint32_t
407PitImpl<Policy>::GetSize () const
408{
409 return super::getPolicy ().size ();
410}
411
412template<class Policy>
413Ptr<Entry>
414PitImpl<Policy>::Begin ()
415{
416 typename super::parent_trie::recursive_iterator item (super::getTrie ()), end (0);
417 for (; item != end; item++)
418 {
419 if (item->payload () == 0) continue;
420 break;
421 }
422
423 if (item == end)
424 return End ();
425 else
426 return item->payload ();
427}
428
429template<class Policy>
430Ptr<Entry>
431PitImpl<Policy>::End ()
432{
433 return 0;
434}
435
436template<class Policy>
437Ptr<Entry>
438PitImpl<Policy>::Next (Ptr<Entry> from)
439{
440 if (from == 0) return 0;
441
442 typename super::parent_trie::recursive_iterator
443 item (*StaticCast< entry > (from)->to_iterator ()),
444 end (0);
445
446 for (item++; item != end; item++)
447 {
448 if (item->payload () == 0) continue;
449 break;
450 }
451
452 if (item == end)
453 return End ();
454 else
455 return item->payload ();
456}
457
458
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700459} // namespace pit
460} // namespace ndn
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700461} // namespace ns3
462
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700463#endif /* NDN_PIT_IMPL_H */