blob: 83fad0998e033fa8b41d0668b029e8910f91b869 [file] [log] [blame]
Alexander Afanasyevc74a6022011-08-15 20:01:35 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2//
3// Copyright (c) 2010,2011 UCLA
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:
19//
20
21#ifndef CCNX_PIT_H
22#define CCNX_PIT_H
23
24#include "ns3/nstime.h"
25#include "hash-helper.h"
26#include <list>
27
28namespace ns3 {
29
30class Ccnx;
31class PitEntry;
32class PitIncomingInterest;
33typedef pair<PitEntry*,PitIncomingInterest*> PitExpirationEntry;
34typedef list<PitExpirationEntry>::iterator PitExpirationIterator;
35
36struct PitIncomingInterest
37{
38 int interfaceIndex; // interface index of the incoming Interest
39 Time expireTime; // life time of the incoming Interest
40 int nonce; // nonce of the last received incoming Interest on this interface
41
42 PitExpirationIterator expirationPosition;
43
44public:
45PitIncomingInterest( int _interface, clocktype _expire, int _nonce )
46: interfaceIndex(_interface)
47, expireTime(_expire)
48 , nonce(_nonce)
49 { };
50
51 bool operator==( const PitIncomingInterest &dst ) { return interfaceIndex==dst.interfaceIndex; }
52 bool operator==( int interface ) { return interfaceIndex==interface; }
53};
54
55struct PitOutgoingInterest
56{
57 int interfaceIndex;
58 clocktype sendTime; //time when the first outgoing interest is sent
59 int retxNum; //number of retransmission
60 int nonce; //nonce of the outgoing Interest
61 bool outstanding; //flag to indicate that this interest is currently pending
62 bool waitingInVain; //when flag is set, we do not expect data for this interest, only a small hope that it will happen
63
64public:
65PitOutgoingInterest( int interface, clocktype time, int nonce )
66: interfaceIndex(interface)
67, sendTime( time )
68 , retxNum( 0 )
69 , nonce( nonce )
70 , outstanding( true )
71 , waitingInVain( false )
72 { };
73
74 bool operator==( const PitIncomingInterest &dst ) { return interfaceIndex==dst.interfaceIndex; }
75 bool operator==( int interface ) { return interfaceIndex==interface; }
76};
77
78
79//structure for PIT entry
80struct PitEntry
81{
82 string contentName;
83 list<PitIncomingInterest> incomingInterests;
84 list<PitOutgoingInterest> outgoingInterests;
85
86 bool timerExpired;
87 int counterExpirations; //whether timer is expired (+ number of times timer expired)
88
89 /**
90 * This variable provides a list of interfaces that will be tried to propagate interest
91 *
92 * It should be initialized with all available interfaces upon reception of first or
93 * any retransmitted (i.e., after STO expired), but not duplicate interests
94 *
95 * Reaction to duplicate interests depends on strategy.
96 *
97 * In case of flooding, this variable should always be empty (it is filled initially with
98 * all avaialble interfaces and then immediately emptied by interest flooding)
99 *
100 * In case of routing strategies, this list will guide (and limit) the local recovery process
101 */
102 list<int> availableInterfaces;
103
104 Message *timerMsg; //the timer message, used to cancel message if data is received
105
106 // Changing PIT removal policy. From now on it will be deleted only when all outgoing
107 // interests are satisfied
108 //
109 // bool dontDeleteOnFirstData; //don't delete when first data packet comes
110 // //(PIT will be deleted only upon timeout or reception data
111 // //packets or prunes for all outgoing interests)
112
113public:
114PitEntry()
115: timerExpired( false )
116, counterExpirations( 0 )
117 , timerMsg( NULL )
118 { }
119
120 inline void fillAvailableInterfacesFromFIB( const FibEntry &fe );
121
122 // Find best candidate, skipping `skip' first candidates (modulo availableInterfaces.size())
123 // !!! assert( availableInterfaces.size()>0 ) !!!
124 inline int findBestCandidate( int skip = 0 );
125
126 // Get number of outgoing interests that we're expecting data from
127 inline size_t numberOfPromisingInterests( ) const;
128};
129
130typedef string_key_hash_t<PitEntry>::point_iterator PitIterator;
131typedef string_key_hash_t<PitEntry>::iterator PitRangeIterator;
132
133typedef list<PitIncomingInterest>::iterator PitIncomingIterator;
134typedef list<PitOutgoingInterest>::iterator PitOutgoingIterator;
135typedef list<PitOutgoingInterest>::const_iterator PitOutgoingConstIterator;
136
137typedef map<int,int> PitCounter;
138typedef map<int,int>::iterator PitCounterIterator;
139
140typedef map<int,double> PitBucket;
141typedef map<int,double>::iterator PitBucketIterator;
142
143
144////////////////////////////////////////////////////////////////////////
145////////////////////////////////////////////////////////////////////////
146
147// class implementing Pending Interests Table
148class CcnxPit
149{
150 public:
151 /**
152 * PIT constructor
153 */
154 CcnxPit( Ccnx &node );
155 virtual ~CcnxPit( );
156
157 //Find corresponding PIT entry for the given content name
158 PitIterator lookup( const string &prefix );
159 bool isValid( const PitIterator &it ) { return it!=_pit.end(); }
160
161 inline PitIncomingIterator findIncoming( PitEntry &pe, int interfaceIndex );
162 inline bool isValid( PitEntry &pe, PitIncomingIterator it );
163 inline PitOutgoingIterator findOutgoing( PitEntry &pe, int interfaceIndex );
164 inline bool isValid( PitEntry &pe, PitOutgoingIterator it );
165
166 // Add a new PIT entry and a correspondent new incoming interest
167 bool add( const string &contentName, const PitIncomingInterest &interest );
168
169 // Add a new outgoing interest
170 int add( PitEntry &pe, const PitOutgoingInterest &interest );
171
172 // remove a PIT entry
173 void erase( const string &contentName );
174
175 // inline bool InterestAlreadyForwarded( PitEntry &pe, int interfaceIndex );
176
177 // Remove expired records from PIT
178 void cleanExpired( clocktype time );
179
180 // Dump content store entries
181 void dump( );
182
183 // Reset pending state in outgoing interests
184 void resetPendingState( PitEntry &pe );
185
186 // // Check if there are any interfaces that we haven't sent data to yet
187 // bool areFreeInterfaces( PitEntry &pe, int interface );
188
189 // Periodically generate pre-calculated number of tokens (leak buckets)
190 void leakBuckets( );
191
192 // Selectively leak a bucket
193 void leakBucket( int interface, int amount );
194
195 // Delete incoming interest for the interface
196 bool deleteIncomingInterest( PitEntry &pe, int interfaceIndex );
197
198 // Remove all incoming interests
199 void deleteAllIncomingInterests( PitEntry &pe );
200
201 public:
202 PitBucket maxBucketsPerInterface; // maximum number of buckets. Automatically computed based on link capacity
203 // averaging over 1 second (bandwidth * 1second)
204 PitBucket leakSize; // size of a periodic bucket leak
205
206 private:
207 bool add( PitEntry &pe, const PitIncomingInterest &interest );
208 void deleteIncomingInterest( PitEntry &pe, PitIncomingIterator it );
209
210 private:
211 Ccnx &_node;
212
213 string_key_hash_t<PitEntry> _pit;
214
215 list<PitExpirationEntry> _pitExpirationList; //list of incoming Interests sorted by expiration time
216
217 PitBucket _bucketsPerInterface; // pending interface counter per interface
218
219 QNThreadMutex _pitMutex; // just to make sure
220};
221
222////////////////////////////////////////////////////////////////////////
223////////////////////////////////////////////////////////////////////////
224
225PitIncomingIterator CcnxPit::findIncoming( PitEntry &pe, int interfaceIndex )
226{
227 return find( pe.incomingInterests.begin( ),
228 pe.incomingInterests.end( ),
229 interfaceIndex );
230}
231
232PitOutgoingIterator CcnxPit::findOutgoing( PitEntry &pe, int interfaceIndex )
233{
234 return find( pe.outgoingInterests.begin( ),
235 pe.outgoingInterests.end( ),
236 interfaceIndex );
237}
238
239bool CcnxPit::isValid( PitEntry &pe, PitIncomingIterator it )
240{
241 return it!=pe.incomingInterests.end( );
242}
243
244bool CcnxPit::isValid( PitEntry &pe, PitOutgoingIterator it )
245{
246 return it!=pe.outgoingInterests.end( );
247}
248
249int PitEntry::findBestCandidate( int skip/* = 0*/ )
250{
251 assert( availableInterfaces.size()>0 );
252
253 skip = skip % availableInterfaces.size();
254 list<int>::iterator candidate = availableInterfaces.begin( );
255 while( skip>0 /* && candidate!=availableInterfaces.end() */ ) { skip--; candidate++; }
256
257 return *candidate;
258}
259
260size_t PitEntry::numberOfPromisingInterests( ) const
261{
262 size_t count = 0;
263
264 for( PitOutgoingConstIterator i = outgoingInterests.begin();
265 i!=outgoingInterests.end();
266 i++ )
267 {
268 if( !i->waitingInVain ) count++;
269 }
270
271 return count;
272}
273
274} // namespace ns3
275
276#endif /* CCNX_PIT_H */