NS-3 based Named Data Networking (NDN) simulator
ndnSIM: NDN, CCN, CCNx, content centric networks
API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
ndn-consumer.cc
1 /* -*- 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
19  */
20 
21 #include "ndn-consumer.h"
22 #include "ns3/ptr.h"
23 #include "ns3/log.h"
24 #include "ns3/simulator.h"
25 #include "ns3/packet.h"
26 #include "ns3/callback.h"
27 #include "ns3/string.h"
28 #include "ns3/boolean.h"
29 #include "ns3/uinteger.h"
30 #include "ns3/integer.h"
31 #include "ns3/double.h"
32 
33 #include "ns3/ndn-app-face.h"
34 #include "ns3/ndn-interest.h"
35 #include "ns3/ndn-data.h"
36 #include "ns3/ndnSIM/utils/ndn-fw-hop-count-tag.h"
37 #include "ns3/ndnSIM/utils/ndn-rtt-mean-deviation.h"
38 
39 #include <boost/ref.hpp>
40 
41 #include "ns3/names.h"
42 
43 NS_LOG_COMPONENT_DEFINE ("ndn.Consumer");
44 
45 namespace ns3 {
46 namespace ndn {
47 
48 NS_OBJECT_ENSURE_REGISTERED (Consumer);
49 
50 TypeId
51 Consumer::GetTypeId (void)
52 {
53  static TypeId tid = TypeId ("ns3::ndn::Consumer")
54  .SetGroupName ("Ndn")
55  .SetParent<App> ()
56  .AddAttribute ("StartSeq", "Initial sequence number",
57  IntegerValue (0),
58  MakeIntegerAccessor(&Consumer::m_seq),
59  MakeIntegerChecker<int32_t>())
60 
61  .AddAttribute ("Prefix","Name of the Interest",
62  StringValue ("/"),
63  MakeNameAccessor (&Consumer::m_interestName),
64  MakeNameChecker ())
65  .AddAttribute ("LifeTime", "LifeTime for interest packet",
66  StringValue ("2s"),
67  MakeTimeAccessor (&Consumer::m_interestLifeTime),
68  MakeTimeChecker ())
69 
70  .AddAttribute ("RetxTimer",
71  "Timeout defining how frequent retransmission timeouts should be checked",
72  StringValue ("50ms"),
73  MakeTimeAccessor (&Consumer::GetRetxTimer, &Consumer::SetRetxTimer),
74  MakeTimeChecker ())
75 
76  .AddTraceSource ("LastRetransmittedInterestDataDelay", "Delay between last retransmitted Interest and received Data",
77  MakeTraceSourceAccessor (&Consumer::m_lastRetransmittedInterestDataDelay))
78 
79  .AddTraceSource ("FirstInterestDataDelay", "Delay between first transmitted Interest and received Data",
80  MakeTraceSourceAccessor (&Consumer::m_firstInterestDataDelay))
81  ;
82 
83  return tid;
84 }
85 
87  : m_rand (0, std::numeric_limits<uint32_t>::max ())
88  , m_seq (0)
89  , m_seqMax (0) // don't request anything
90 {
91  NS_LOG_FUNCTION_NOARGS ();
92 
93  m_rtt = CreateObject<RttMeanDeviation> ();
94 }
95 
96 void
97 Consumer::SetRetxTimer (Time retxTimer)
98 {
99  m_retxTimer = retxTimer;
100  if (m_retxEvent.IsRunning ())
101  {
102  // m_retxEvent.Cancel (); // cancel any scheduled cleanup events
103  Simulator::Remove (m_retxEvent); // slower, but better for memory
104  }
105 
106  // schedule even with new timeout
107  m_retxEvent = Simulator::Schedule (m_retxTimer,
109 }
110 
111 Time
113 {
114  return m_retxTimer;
115 }
116 
117 void
119 {
120  Time now = Simulator::Now ();
121 
122  Time rto = m_rtt->RetransmitTimeout ();
123  // NS_LOG_DEBUG ("Current RTO: " << rto.ToDouble (Time::S) << "s");
124 
125  while (!m_seqTimeouts.empty ())
126  {
127  SeqTimeoutsContainer::index<i_timestamp>::type::iterator entry =
128  m_seqTimeouts.get<i_timestamp> ().begin ();
129  if (entry->time + rto <= now) // timeout expired?
130  {
131  uint32_t seqNo = entry->seq;
132  m_seqTimeouts.get<i_timestamp> ().erase (entry);
133  OnTimeout (seqNo);
134  }
135  else
136  break; // nothing else to do. All later packets need not be retransmitted
137  }
138 
139  m_retxEvent = Simulator::Schedule (m_retxTimer,
141 }
142 
143 // Application Methods
144 void
145 Consumer::StartApplication () // Called at time specified by Start
146 {
147  NS_LOG_FUNCTION_NOARGS ();
148 
149  // do base stuff
151 
153 }
154 
155 void
156 Consumer::StopApplication () // Called at time specified by Stop
157 {
158  NS_LOG_FUNCTION_NOARGS ();
159 
160  // cancel periodic packet generation
161  Simulator::Cancel (m_sendEvent);
162 
163  // cleanup base stuff
165 }
166 
167 void
169 {
170  if (!m_active) return;
171 
172  NS_LOG_FUNCTION_NOARGS ();
173 
174  uint32_t seq=std::numeric_limits<uint32_t>::max (); //invalid
175 
176  while (m_retxSeqs.size ())
177  {
178  seq = *m_retxSeqs.begin ();
179  m_retxSeqs.erase (m_retxSeqs.begin ());
180  break;
181  }
182 
183  if (seq == std::numeric_limits<uint32_t>::max ())
184  {
185  if (m_seqMax != std::numeric_limits<uint32_t>::max ())
186  {
187  if (m_seq >= m_seqMax)
188  {
189  return; // we are totally done
190  }
191  }
192 
193  seq = m_seq++;
194  }
195 
196  //
197  Ptr<Name> nameWithSequence = Create<Name> (m_interestName);
198  nameWithSequence->appendSeqNum (seq);
199  //
200 
201  Ptr<Interest> interest = Create<Interest> ();
202  interest->SetNonce (m_rand.GetValue ());
203  interest->SetName (nameWithSequence);
204  interest->SetInterestLifetime (m_interestLifeTime);
205 
206  // NS_LOG_INFO ("Requesting Interest: \n" << *interest);
207  NS_LOG_INFO ("> Interest for " << seq);
208 
209  WillSendOutInterest (seq);
210 
211  FwHopCountTag hopCountTag;
212  interest->GetPayload ()->AddPacketTag (hopCountTag);
213 
214  m_transmittedInterests (interest, this, m_face);
215  m_face->ReceiveInterest (interest);
216 
218 }
219 
221 // Process incoming packets //
223 
224 
225 void
226 Consumer::OnData (Ptr<const Data> data)
227 {
228  if (!m_active) return;
229 
230  App::OnData (data); // tracing inside
231 
232  NS_LOG_FUNCTION (this << data);
233 
234  // NS_LOG_INFO ("Received content object: " << boost::cref(*data));
235 
236  uint32_t seq = data->GetName ().get (-1).toSeqNum ();
237  NS_LOG_INFO ("< DATA for " << seq);
238 
239  int hopCount = -1;
240  FwHopCountTag hopCountTag;
241  if (data->GetPayload ()->PeekPacketTag (hopCountTag))
242  {
243  hopCount = hopCountTag.Get ();
244  }
245 
246  SeqTimeoutsContainer::iterator entry = m_seqLastDelay.find (seq);
247  if (entry != m_seqLastDelay.end ())
248  {
249  m_lastRetransmittedInterestDataDelay (this, seq, Simulator::Now () - entry->time, hopCount);
250  }
251 
252  entry = m_seqFullDelay.find (seq);
253  if (entry != m_seqFullDelay.end ())
254  {
255  m_firstInterestDataDelay (this, seq, Simulator::Now () - entry->time, m_seqRetxCounts[seq], hopCount);
256  }
257 
258  m_seqRetxCounts.erase (seq);
259  m_seqFullDelay.erase (seq);
260  m_seqLastDelay.erase (seq);
261 
262  m_seqTimeouts.erase (seq);
263  m_retxSeqs.erase (seq);
264 
265  m_rtt->AckSeq (SequenceNumber32 (seq));
266 }
267 
268 void
269 Consumer::OnNack (Ptr<const Interest> interest)
270 {
271  if (!m_active) return;
272 
273  App::OnNack (interest); // tracing inside
274 
275  // NS_LOG_DEBUG ("Nack type: " << interest->GetNack ());
276 
277  // NS_LOG_FUNCTION (interest->GetName ());
278 
279  // NS_LOG_INFO ("Received NACK: " << boost::cref(*interest));
280  uint32_t seq = interest->GetName ().get (-1).toSeqNum ();
281  NS_LOG_INFO ("< NACK for " << seq);
282  // std::cout << Simulator::Now ().ToDouble (Time::S) << "s -> " << "NACK for " << seq << "\n";
283 
284  // put in the queue of interests to be retransmitted
285  // NS_LOG_INFO ("Before: " << m_retxSeqs.size ());
286  m_retxSeqs.insert (seq);
287  // NS_LOG_INFO ("After: " << m_retxSeqs.size ());
288 
289  m_seqTimeouts.erase (seq);
290 
291  m_rtt->IncreaseMultiplier (); // Double the next RTO ??
293 }
294 
295 void
296 Consumer::OnTimeout (uint32_t sequenceNumber)
297 {
298  NS_LOG_FUNCTION (sequenceNumber);
299  // std::cout << Simulator::Now () << ", TO: " << sequenceNumber << ", current RTO: " << m_rtt->RetransmitTimeout ().ToDouble (Time::S) << "s\n";
300 
301  m_rtt->IncreaseMultiplier (); // Double the next RTO
302  m_rtt->SentSeq (SequenceNumber32 (sequenceNumber), 1); // make sure to disable RTT calculation for this sample
303  m_retxSeqs.insert (sequenceNumber);
305 }
306 
307 void
308 Consumer::WillSendOutInterest (uint32_t sequenceNumber)
309 {
310  NS_LOG_DEBUG ("Trying to add " << sequenceNumber << " with " << Simulator::Now () << ". already " << m_seqTimeouts.size () << " items");
311 
312  m_seqTimeouts.insert (SeqTimeout (sequenceNumber, Simulator::Now ()));
313  m_seqFullDelay.insert (SeqTimeout (sequenceNumber, Simulator::Now ()));
314 
315  m_seqLastDelay.erase (sequenceNumber);
316  m_seqLastDelay.insert (SeqTimeout (sequenceNumber, Simulator::Now ()));
317 
318  m_seqRetxCounts[sequenceNumber] ++;
319 
320  m_rtt->SentSeq (SequenceNumber32 (sequenceNumber), 1);
321 }
322 
323 
324 } // namespace ndn
325 } // namespace ns3
bool m_active
Flag to indicate that application is active (set by StartApplication and StopApplication) ...
Definition: ndn-app.h:106
virtual void OnTimeout(uint32_t sequenceNumber)
Timeout event.
Consumer()
Default constructor Sets up randomizer function and packet sequence number.
Definition: ndn-consumer.cc:86
Name m_interestName
NDN Name of the Interest (use Name)
Definition: ndn-consumer.h:138
virtual void StartApplication()
Called at time specified by Start.
Definition: ndn-app.cc:119
virtual void ScheduleNextPacket()=0
Constructs the Interest packet and sends it using a callback to the underlying NDN protocol...
TracedCallback< Ptr< const Interest >, Ptr< App >, Ptr< Face > > m_transmittedInterests
App-level trace of transmitted Interests.
Definition: ndn-app.h:120
UniformVariable m_rand
nonce generator
Definition: ndn-consumer.h:127
Time m_retxTimer
Currently estimated retransmission timer.
Definition: ndn-consumer.h:132
EventId m_sendEvent
EventId of pending "send packet" event.
Definition: ndn-consumer.h:131
virtual void OnData(Ptr< const Data > contentObject)
Method that will be called every time new Data arrives.
EventId m_retxEvent
Event to check whether or not retransmission should be performed.
Definition: ndn-consumer.h:133
Ptr< RttEstimator > m_rtt
RTT estimator.
Definition: ndn-consumer.h:135
virtual void OnNack(Ptr< const Interest > interest)
Method that will be called every time new NACK arrives.
Definition: ndn-app.cc:104
Time GetRetxTimer() const
Returns the frequency of checking the retransmission timeouts.
void CheckRetxTimeout()
Checks if the packet need to be retransmitted becuase of retransmission timer expiration.
uint32_t m_seqMax
maximum number of sequence number
Definition: ndn-consumer.h:130
virtual void OnData(Ptr< const Data > contentObject)
Method that will be called every time new Data arrives.
Definition: ndn-app.cc:111
void SendPacket()
Actually send packet.
virtual void StopApplication()
Called at time specified by Stop.
Definition: ndn-app.cc:140
virtual void WillSendOutInterest(uint32_t sequenceNumber)
An event that is fired just before an Interest packet is actually send out (send is inevitable) ...
virtual void StartApplication()
Called at time specified by Start.
uint32_t Get() const
Get value of hop count.
Packet tag that is used to track hop count for Interest-Data pairs.
uint32_t m_seq
currently requested sequence number
Definition: ndn-consumer.h:129
App()
Default constructor.
Definition: ndn-app.cc:66
Ptr< Face > m_face
automatically created application face through which application communicates
Definition: ndn-app.h:107
virtual void StopApplication()
Called at time specified by Stop.
Time m_interestLifeTime
LifeTime for interest packet.
Definition: ndn-consumer.h:139
void SetRetxTimer(Time retxTimer)
Modifies the frequency of checking the retransmission timeouts.
Definition: ndn-consumer.cc:97
virtual void OnNack(Ptr< const Interest > interest)
Method that will be called every time new NACK arrives.