blob: 2dfd39dbe144e21d3ec42bad76e9f7888de92ec1 [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);
198 NS_ASSERT_MSG (fibEntry != 0,
199 "There should be at least default route set" <<
200 " Prefix = "<< header->GetName() << "NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700201
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700202
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700203 Ptr< entry > newEntry = ns3::Create< entry > (boost::ref (*this), header, fibEntry);
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700204 std::pair< super::iterator, bool > result = super::insert (header->GetName (), newEntry);
205 if (result.first != super::end ())
206 {
207 if (result.second)
208 {
209 newEntry->SetTrie (result.first);
210 return newEntry;
211 }
212 else
213 {
214 // should we do anything?
215 // update payload? add new payload?
216 return result.first->payload ();
217 }
218 }
219 else
220 return 0;
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700221}
222
223
224void
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700225CcnxPitImpl::MarkErased (Ptr<CcnxPitEntry> item)
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700226{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700227 // entry->SetExpireTime (Simulator::Now () + m_PitEntryPruningTimout);
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700228 super::erase (StaticCast< entry > (item)->to_iterator ());
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700229}
230
231
232void
233CcnxPitImpl::Print (std::ostream& os) const
234{
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700235 // !!! unordered_set imposes "random" order of item in the same level !!!
236 super::parent_trie::const_recursive_iterator item (super::getTrie ()), end (0);
237 for (; item != end; item++)
238 {
239 if (item->payload () == 0) continue;
240
241 os << item->payload ()->GetPrefix () << "\t" << *item->payload () << "\n";
242 }
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700243}
244
Alexander Afanasyevf1e013f2012-07-11 17:59:40 -0700245uint32_t
246CcnxPitImpl::GetSize () const
247{
248 return super::getPolicy ().size ();
249}
250
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700251Ptr<CcnxPitEntry>
252CcnxPitImpl::Begin ()
253{
254 super::parent_trie::recursive_iterator item (super::getTrie ()), end (0);
255 for (; item != end; item++)
256 {
257 if (item->payload () == 0) continue;
258 break;
259 }
260
261 if (item == end)
262 return End ();
263 else
264 return item->payload ();
265}
266
267Ptr<CcnxPitEntry>
268CcnxPitImpl::End ()
269{
270 return 0;
271}
272
273Ptr<CcnxPitEntry>
274CcnxPitImpl::Next (Ptr<CcnxPitEntry> from)
275{
276 if (from == 0) return 0;
277
278 super::parent_trie::recursive_iterator
Alexander Afanasyev36b45772012-07-10 16:57:42 -0700279 item (*StaticCast< entry > (from)->to_iterator ()),
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700280 end (0);
281
282 for (item++; item != end; item++)
283 {
284 if (item->payload () == 0) continue;
285 break;
286 }
287
288 if (item == end)
289 return End ();
290 else
291 return item->payload ();
292}
293
294
Alexander Afanasyev11f7bb42012-07-09 17:06:30 -0700295} // namespace ns3