A Discrete-Event Network Simulator
API
tbf-queue-disc.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017 Kungliga Tekniska Högskolan
4  * 2017 Universita' degli Studi di Napoli Federico II
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * TBF, The Token Bucket Filter Queueing discipline
20  *
21  * This implementation is based on linux kernel code by
22  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
23  * Dmitry Torokhov <dtor@mail.ru> - allow attaching inner qdiscs -
24  * original idea by Martin Devera
25  *
26  * Implemented in ns-3 by: Surya Seetharaman <suryaseetharaman.9@gmail.com>
27  * Stefano Avallone <stavallo@unina.it>
28  */
29 
30 #include "ns3/log.h"
31 #include "ns3/enum.h"
32 #include "ns3/simulator.h"
33 #include "ns3/uinteger.h"
34 #include "ns3/attribute.h"
35 #include "ns3/object-factory.h"
36 #include "ns3/drop-tail-queue.h"
37 #include "ns3/net-device-queue-interface.h"
38 #include "tbf-queue-disc.h"
39 
40 namespace ns3 {
41 
42 NS_LOG_COMPONENT_DEFINE ("TbfQueueDisc");
43 
44 NS_OBJECT_ENSURE_REGISTERED (TbfQueueDisc);
45 
47 {
48  static TypeId tid = TypeId ("ns3::TbfQueueDisc")
49  .SetParent<QueueDisc> ()
50  .SetGroupName ("TrafficControl")
51  .AddConstructor<TbfQueueDisc> ()
52  .AddAttribute ("MaxSize",
53  "The max queue size",
54  QueueSizeValue (QueueSize ("1000p")),
58  .AddAttribute ("Burst",
59  "Size of the first bucket in bytes",
60  UintegerValue (125000),
62  MakeUintegerChecker<uint32_t> ())
63  .AddAttribute ("Mtu",
64  "Size of the second bucket in bytes. If null, it is initialized"
65  " to the MTU of the attached NetDevice (if any)",
66  UintegerValue (0),
68  MakeUintegerChecker<uint32_t> ())
69  .AddAttribute ("Rate",
70  "Rate at which tokens enter the first bucket in bps or Bps.",
71  DataRateValue (DataRate ("125KB/s")),
74  .AddAttribute ("PeakRate",
75  "Rate at which tokens enter the second bucket in bps or Bps."
76  "If null, there is no second bucket",
77  DataRateValue (DataRate ("0KB/s")),
80  .AddTraceSource ("TokensInFirstBucket",
81  "Number of First Bucket Tokens in bytes",
83  "ns3::TracedValueCallback::Uint32")
84  .AddTraceSource ("TokensInSecondBucket",
85  "Number of Second Bucket Tokens in bytes",
87  "ns3::TracedValueCallback::Uint32")
88  ;
89 
90  return tid;
91 }
92 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
100 {
101  NS_LOG_FUNCTION (this);
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION (this);
109 }
110 
111 void
112 TbfQueueDisc::SetBurst (uint32_t burst)
113 {
114  NS_LOG_FUNCTION (this << burst);
115  m_burst = burst;
116 }
117 
118 uint32_t
120 {
121  NS_LOG_FUNCTION (this);
122  return m_burst;
123 }
124 
125 void
126 TbfQueueDisc::SetMtu (uint32_t mtu)
127 {
128  NS_LOG_FUNCTION (this << mtu);
129  m_mtu = mtu;
130 }
131 
132 uint32_t
134 {
135  NS_LOG_FUNCTION (this);
136  return m_mtu;
137 }
138 
139 void
141 {
142  NS_LOG_FUNCTION (this << rate);
143  m_rate = rate;
144 }
145 
146 DataRate
148 {
149  NS_LOG_FUNCTION (this);
150  return m_rate;
151 }
152 
153 void
155 {
156  NS_LOG_FUNCTION (this << peakRate);
157  m_peakRate = peakRate;
158 }
159 
160 DataRate
162 {
163  NS_LOG_FUNCTION (this);
164  return m_peakRate;
165 }
166 
167 uint32_t
169 {
170  NS_LOG_FUNCTION (this);
171  return m_btokens;
172 }
173 
174 uint32_t
176 {
177  NS_LOG_FUNCTION (this);
178  return m_ptokens;
179 }
180 
181 bool
183 {
184  NS_LOG_FUNCTION (this << item);
185 
186  bool retval = GetQueueDiscClass (0)->GetQueueDisc ()->Enqueue (item);
187 
188  // If Queue::Enqueue fails, QueueDisc::Drop is called by the child queue
189  // disc because QueueDisc::AddQueueDiscClass sets the drop callback
190 
191  NS_LOG_LOGIC ("Current queue size: " << GetNPackets () << " packets, " << GetNBytes () << " bytes");
192 
193  return retval;
194 }
195 
198 {
199  NS_LOG_FUNCTION (this);
200 
202 
203  if (!item)
204  {
205  NS_LOG_LOGIC ("No packet returned");
206  return 0;
207  }
208 
209  NS_LOG_LOGIC ("Current queue size: " << GetNPackets () << " packets, " << GetNBytes () << " bytes");
210 
211  return item;
212 }
213 
216 {
217  NS_LOG_FUNCTION (this);
218  Ptr<const QueueDiscItem> itemPeek = GetQueueDiscClass (0)->GetQueueDisc ()->Peek ();
219 
220  if (itemPeek)
221  {
222  uint32_t pktSize = itemPeek->GetSize ();
223  NS_LOG_LOGIC ("Next packet size " << pktSize);
224 
225  int64_t btoks = 0;
226  int64_t ptoks = 0;
227  Time now = Simulator::Now ();
228 
229  double delta = (now - m_timeCheckPoint).GetSeconds ();
230  NS_LOG_LOGIC ("Time Difference delta " << delta);
231 
232  if (m_peakRate > DataRate ("0bps"))
233  {
234  ptoks = m_ptokens + round (delta * (m_peakRate.GetBitRate () / 8));
235  if (ptoks > m_mtu)
236  {
237  ptoks = m_mtu;
238  }
239  NS_LOG_LOGIC ("Number of ptokens we can consume " << ptoks);
240  NS_LOG_LOGIC ("Required to dequeue next packet " << pktSize);
241  ptoks -= pktSize;
242  }
243 
244  btoks = m_btokens + round (delta * (m_rate.GetBitRate () / 8));
245 
246  if (btoks > m_burst)
247  {
248  btoks = m_burst;
249  }
250 
251  NS_LOG_LOGIC ("Number of btokens we can consume " << btoks);
252  NS_LOG_LOGIC ("Required to dequeue next packet " << pktSize);
253  btoks -= pktSize;
254 
255  if ((btoks|ptoks) >= 0) // else packet blocked
256  {
257  Ptr<QueueDiscItem> item = GetQueueDiscClass (0)->GetQueueDisc ()->DequeuePeeked ();
258  if (!item)
259  {
260  NS_LOG_DEBUG ("That's odd! Expecting the peeked packet, we got no packet.");
261  return item;
262  }
263 
264  m_timeCheckPoint = now;
265  m_btokens = btoks;
266  m_ptokens = ptoks;
267 
268  NS_LOG_LOGIC (m_btokens << " btokens and " << m_ptokens << " ptokens after packet dequeue");
269  NS_LOG_LOGIC ("Current queue size: " << GetNPackets () << " packets, " << GetNBytes () << " bytes");
270 
271  return item;
272  }
273 
274  // the watchdog timer setup.
275  /* A packet gets blocked if the above if condition is not satisfied, i.e.
276  both the ptoks and btoks are less than zero. In that case we have to
277  schedule the waking of queue when enough tokens are available. */
278  if (m_id.IsExpired () == true)
279  {
280  Time requiredDelayTime = std::max (m_rate.CalculateBytesTxTime (-btoks),
282 
283  m_id = Simulator::Schedule (requiredDelayTime, &QueueDisc::Run, this);
284  NS_LOG_LOGIC("Waking Event Scheduled in " << requiredDelayTime);
285  }
286  }
287  return 0;
288 }
289 
290 bool
292 {
293  NS_LOG_FUNCTION (this);
294  if (GetNInternalQueues () > 0)
295  {
296  NS_LOG_ERROR ("TbfQueueDisc cannot have internal queues");
297  return false;
298  }
299 
300  if (GetNPacketFilters () > 0)
301  {
302  NS_LOG_ERROR ("TbfQueueDisc cannot have packet filters");
303  return false;
304  }
305 
306  if (GetNQueueDiscClasses () == 0)
307  {
308  // create a FIFO queue disc
309  ObjectFactory factory;
310  factory.SetTypeId ("ns3::FifoQueueDisc");
311  Ptr<QueueDisc> qd = factory.Create<QueueDisc> ();
312 
313  if (!qd->SetMaxSize (GetMaxSize ()))
314  {
315  NS_LOG_ERROR ("Cannot set the max size of the child queue disc to that of TbfQueueDisc");
316  return false;
317  }
318  qd->Initialize ();
319 
320  Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass> ();
321  c->SetQueueDisc (qd);
322  AddQueueDiscClass (c);
323  }
324 
325  if (GetNQueueDiscClasses () != 1)
326  {
327  NS_LOG_ERROR ("TbfQueueDisc needs 1 child queue disc");
328  return false;
329  }
330 
331  if (m_mtu == 0 && GetNetDevice ())
332  {
333  m_mtu = GetNetDevice ()->GetMtu ();
334  }
335 
336  if (m_mtu == 0 && m_peakRate > DataRate ("0bps"))
337  {
338  NS_LOG_ERROR ("A non-null peak rate has been set, but the mtu is null. No packet will be dequeued");
339  return false;
340  }
341 
342  if (m_burst <= m_mtu)
343  {
344  NS_LOG_WARN ("The size of the first bucket (" << m_burst << ") should be "
345  << "greater than the size of the second bucket (" << m_mtu << ").");
346  }
347 
348  if (m_peakRate > DataRate ("0bps") && m_peakRate <= m_rate)
349  {
350  NS_LOG_WARN ("The rate for the second bucket (" << m_peakRate << ") should be "
351  << "greater than the rate for the first bucket (" << m_rate << ").");
352  }
353 
354  return true;
355 }
356 
357 void
359 {
360  NS_LOG_FUNCTION (this);
361  // Token Buckets are full at the beginning.
362  m_btokens = m_burst;
363  m_ptokens = m_mtu;
364  // Initialising other variables to 0.
366  m_id = EventId ();
367 }
368 
369 } // namespace ns3
virtual void DoDispose(void)
Dispose of the object.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
DataRate m_peakRate
Rate at which tokens enter the second bucket.
uint32_t GetNQueueDiscClasses(void) const
Get the number of queue disc classes.
Definition: queue-disc.cc:652
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Class for representing queue sizes.
Definition: queue-size.h:94
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:620
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
TracedValue< uint32_t > m_btokens
Current number of tokens in first bucket.
uint32_t GetMtu(void) const
Get the size of the second bucket in bytes.
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:235
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:447
DataRate m_rate
Rate at which tokens enter the first bucket.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSecondBucketTokens(void) const
Get the current number of tokens inside the second bucket in bytes.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
void SetPeakRate(DataRate peakRate)
Set the rate of the tokens entering the second bucket.
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:181
uint32_t GetFirstBucketTokens(void) const
Get the current number of tokens inside the first bucket in bytes.
Used by queue discs with single child queue disc.
Definition: queue-disc.h:106
Ptr< const AttributeChecker > MakeDataRateChecker(void)
Definition: data-rate.cc:30
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
Class for representing data rates.
Definition: data-rate.h:88
TbfQueueDisc()
TbfQueueDisc Constructor.
uint32_t m_mtu
Size of second bucket in bytes.
uint32_t GetNInternalQueues(void) const
Get the number of internal queues.
Definition: queue-disc.cc:594
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1375
#define max(a, b)
Definition: 80211b.c:45
EventId m_id
EventId of the scheduled queue waking event when enough tokens are available.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Hold an unsigned integer type.
Definition: uinteger.h:44
void Run(void)
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets...
Definition: queue-disc.cc:911
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
Ptr< const AttributeAccessor > MakeQueueSizeAccessor(T1 a1)
Definition: queue-size.h:221
virtual void DoDispose(void)
Dispose of the object.
Definition: queue-disc.cc:381
uint32_t GetNPacketFilters(void) const
Get the number of packet filters.
Definition: queue-disc.cc:614
Ptr< const AttributeAccessor > MakeDataRateAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: data-rate.h:242
virtual Ptr< const QueueDiscItem > DoPeek(void)
This function returns a copy of the next packet the queue disc will extract.
Ptr< const AttributeChecker > MakeQueueSizeChecker(void)
Definition: queue-size.cc:29
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time m_timeCheckPoint
Time check-point.
DataRate GetRate(void) const
Get the rate of the tokens entering the first bucket.
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:249
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
void SetMtu(uint32_t mtu)
Set the size of the second bucket in bytes.
void SetBurst(uint32_t burst)
Set the size of the first bucket in bytes.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
static TypeId GetTypeId(void)
Get the type ID.
uint32_t m_burst
Size of first bucket in bytes.
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:103
Instantiate subclasses of ns3::Object.
Ptr< const QueueDiscItem > PeekDequeued(void)
Dequeue a packet and retain it in the queue disc as a requeued packet.
Definition: queue-disc.cc:880
An identifier for simulation events.
Definition: event-id.h:53
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
AttributeValue implementation for DataRate.
Definition: data-rate.h:242
TracedValue< uint32_t > m_ptokens
Current number of tokens in second bucket.
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
Definition: queue-disc.cc:482
A TBF packet queue disc.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:253
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
DataRate GetPeakRate(void) const
Get the rate of the tokens entering the second bucket.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
Ptr< NetDevice > GetNetDevice(void) const
Get the NetDevice on which this queue discipline is installed.
Definition: queue-disc.cc:546
virtual ~TbfQueueDisc()
Destructor.
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
Ptr< QueueDiscClass > GetQueueDiscClass(uint32_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:645
uint32_t GetBurst(void) const
Get the size of the first bucket in bytes.
QueueSize GetMaxSize(void) const
Get the maximum size of the queue disc.
Definition: queue-disc.cc:454
void SetRate(DataRate rate)
Set the rate of the tokens entering the first bucket.
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:440