blob: 9acf867d3e81474bec7a4c1b24047cf15ecddbab [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
21#include "ccnx-pit-impl.h"
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070022
23#include "ns3/ccnx-interest-header.h"
24#include "ns3/ccnx-content-object-header.h"
Alexander Afanasyevf249a192012-07-18 16:52:51 -070025#include "ns3/ccnx-forwarding-strategy.h"
Alexander Afanasyeve3d126f2012-07-16 17:07:31 -070026
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070027#include "ns3/log.h"
28#include "ns3/string.h"
29#include "ns3/uinteger.h"
30#include "ns3/simulator.h"
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070031
32#include <boost/lambda/bind.hpp>
33#include <boost/lambda/lambda.hpp>
34
35NS_LOG_COMPONENT_DEFINE ("CcnxPitImpl");
36
37using namespace boost::tuples;
38using namespace boost;
39namespace ll = boost::lambda;
40
41namespace ns3 {
42
43NS_OBJECT_ENSURE_REGISTERED (CcnxPitImpl);
44
Alexander Afanasyev36b45772012-07-10 16:57:42 -070045
46// CcnxPitEntryImpl::CcnxPitEntryImpl (CcnxPit &pit,
47// Ptr<const CcnxInterestHeader> header,
48// Ptr<CcnxFibEntry> fibEntry)
49// : CcnxPitEntry (pit, header, fibEntry)
50// , item_ (0)
51// {
52// static_cast<CcnxPitImpl&> (m_container).i_time.insert (*this);
53// }
54
55// CcnxPitEntryImpl::~CcnxPitEntryImpl ()
56// {
57// static_cast<CcnxPitImpl&> (m_container).i_time.erase (*this);
58// }
59
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070060TypeId
61CcnxPitImpl::GetTypeId ()
62{
63 static TypeId tid = TypeId ("ns3::CcnxPit")
64 .SetGroupName ("Ccnx")
65 .SetParent<CcnxPit> ()
66 .AddConstructor<CcnxPitImpl> ()
67 .AddAttribute ("MaxSize",
68 "Set maximum number of entries in PIT. If 0, limit is not enforced",
69 StringValue ("0"),
70 MakeUintegerAccessor (&CcnxPitImpl::GetMaxSize, &CcnxPitImpl::SetMaxSize),
71 MakeUintegerChecker<uint32_t> ())
72 ;
73
74 return tid;
75}
76
77CcnxPitImpl::CcnxPitImpl ()
78{
79}
80
81CcnxPitImpl::~CcnxPitImpl ()
82{
83}
84
85uint32_t
86CcnxPitImpl::GetMaxSize () const
87{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070088 return getPolicy ().get_max_size ();
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070089}
90
91void
92CcnxPitImpl::SetMaxSize (uint32_t maxSize)
93{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070094 getPolicy ().set_max_size (maxSize);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -070095}
96
97void
98CcnxPitImpl::NotifyNewAggregate ()
99{
100 if (m_fib == 0)
101 {
102 m_fib = GetObject<CcnxFib> ();
103 }
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700104 if (m_forwardingStrategy == 0)
105 {
106 m_forwardingStrategy = GetObject<CcnxForwardingStrategy> ();
107 }
108
109 CcnxPit::NotifyNewAggregate ();
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700110}
111
112void
113CcnxPitImpl::DoDispose ()
114{
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700115 super::clear ();
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700116
117 m_forwardingStrategy = 0;
118 m_fib = 0;
119
120 CcnxPit::DoDispose ();
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700121}
122
123void CcnxPitImpl::RescheduleCleaning ()
124{
125 m_cleanEvent.Cancel ();
126 if (i_time.empty ())
Alexander Afanasyevf1e013f2012-07-11 17:59:40 -0700127 {
128 NS_LOG_DEBUG ("No items in PIT");
129 return;
130 }
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700131
Alexander Afanasyevf1e013f2012-07-11 17:59:40 -0700132 Time nextEvent = i_time.begin ()->GetExpireTime () - Simulator::Now ();
133 if (nextEvent < 0) nextEvent = Seconds (0);
134
135 NS_LOG_DEBUG ("Schedule next cleaning in " <<
136 nextEvent.ToDouble (Time::S) << "s (at " <<
137 i_time.begin ()->GetExpireTime () << "s abs time");
138 m_cleanEvent = Simulator::Schedule (nextEvent,
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700139 &CcnxPitImpl::CleanExpired, this);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700140}
141
142void
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700143CcnxPitImpl::CleanExpired ()
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700144{
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700145 NS_LOG_LOGIC ("Cleaning PIT. Total: " << i_time.size ());
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700146 Time now = Simulator::Now ();
147
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700148 // uint32_t count = 0;
149 while (!i_time.empty ())
150 {
151 time_index::iterator entry = i_time.begin ();
152 if (entry->GetExpireTime () <= now) // is the record stale?
153 {
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700154 m_forwardingStrategy->WillErasePendingInterest (entry->to_iterator ()->payload ());
Alexander Afanasyev413c7f12012-07-10 17:35:16 -0700155 super::erase (entry->to_iterator ());
156 // // count ++;
157 }
158 else
159 break; // nothing else to do. All later records will not be stale
160 }
161
162 RescheduleCleaning ();
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700163}
164
165Ptr<CcnxPitEntry>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700166CcnxPitImpl::Lookup (const CcnxContentObjectHeader &header)
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700167{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700168 /// @todo use predicate to search with exclude filters
169 super::iterator item = super::longest_prefix_match (header.GetName ());
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700170
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700171 if (item == super::end ())
172 return 0;
173 else
174 return item->payload (); // which could also be 0
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700175}
176
177Ptr<CcnxPitEntry>
178CcnxPitImpl::Lookup (const CcnxInterestHeader &header)
179{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700180 NS_LOG_FUNCTION (header.GetName ());
181 NS_ASSERT_MSG (m_fib != 0, "FIB should be set");
Alexander Afanasyevf249a192012-07-18 16:52:51 -0700182 NS_ASSERT_MSG (m_forwardingStrategy != 0, "Forwarding strategy should be set");
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700183
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700184 super::iterator foundItem, lastItem;
185 bool reachLast;
186 boost::tie (foundItem, reachLast, lastItem) = super::getTrie ().find (header.GetName ());
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700187
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700188 if (!reachLast || lastItem == super::end ())
189 return 0;
190 else
191 return lastItem->payload (); // which could also be 0
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700192}
193
194Ptr<CcnxPitEntry>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700195CcnxPitImpl::Create (Ptr<const CcnxInterestHeader> header)
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700196{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700197 Ptr<CcnxFibEntry> fibEntry = m_fib->LongestPrefixMatch (*header);
Alexander Afanasyev3c5b6a72012-07-20 15:35:48 -0700198 if (fibEntry == 0)
199 return 0;
200
201 // NS_ASSERT_MSG (fibEntry != 0,
202 // "There should be at least default route set" <<
203 // " Prefix = "<< header->GetName() << ", NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700204
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700205 Ptr< entry > newEntry = ns3::Create< entry > (boost::ref (*this), header, fibEntry);
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700206 std::pair< super::iterator, bool > result = super::insert (header->GetName (), newEntry);
207 if (result.first != super::end ())
208 {
209 if (result.second)
210 {
211 newEntry->SetTrie (result.first);
212 return newEntry;
213 }
214 else
215 {
216 // should we do anything?
217 // update payload? add new payload?
218 return result.first->payload ();
219 }
220 }
221 else
222 return 0;
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700223}
224
225
226void
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700227CcnxPitImpl::MarkErased (Ptr<CcnxPitEntry> item)
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700228{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700229 // entry->SetExpireTime (Simulator::Now () + m_PitEntryPruningTimout);
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700230 super::erase (StaticCast< entry > (item)->to_iterator ());
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700231}
232
233
234void
235CcnxPitImpl::Print (std::ostream& os) const
236{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700237 // !!! unordered_set imposes "random" order of item in the same level !!!
238 super::parent_trie::const_recursive_iterator item (super::getTrie ()), end (0);
239 for (; item != end; item++)
240 {
241 if (item->payload () == 0) continue;
242
243 os << item->payload ()->GetPrefix () << "\t" << *item->payload () << "\n";
244 }
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700245}
246
Alexander Afanasyevf1e013f2012-07-11 17:59:40 -0700247uint32_t
248CcnxPitImpl::GetSize () const
249{
250 return super::getPolicy ().size ();
251}
252
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700253Ptr<CcnxPitEntry>
254CcnxPitImpl::Begin ()
255{
256 super::parent_trie::recursive_iterator item (super::getTrie ()), end (0);
257 for (; item != end; item++)
258 {
259 if (item->payload () == 0) continue;
260 break;
261 }
262
263 if (item == end)
264 return End ();
265 else
266 return item->payload ();
267}
268
269Ptr<CcnxPitEntry>
270CcnxPitImpl::End ()
271{
272 return 0;
273}
274
275Ptr<CcnxPitEntry>
276CcnxPitImpl::Next (Ptr<CcnxPitEntry> from)
277{
278 if (from == 0) return 0;
279
280 super::parent_trie::recursive_iterator
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700281 item (*StaticCast< entry > (from)->to_iterator ()),
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700282 end (0);
283
284 for (item++; item != end; item++)
285 {
286 if (item->payload () == 0) continue;
287 break;
288 }
289
290 if (item == end)
291 return End ();
292 else
293 return item->payload ();
294}
295
296
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700297} // namespace ns3