A Discrete-Event Network Simulator
API
tbf-queue-disc.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Kungliga Tekniska Högskolan
3  * 2017 Universita' degli Studi di Napoli Federico II
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  * TBF, The Token Bucket Filter Queueing discipline
19  *
20  * This implementation is based on linux kernel code by
21  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
22  * Dmitry Torokhov <dtor@mail.ru> - allow attaching inner qdiscs -
23  * original idea by Martin Devera
24  *
25  * Implemented in ns-3 by: Surya Seetharaman <suryaseetharaman.9@gmail.com>
26  * Stefano Avallone <stavallo@unina.it>
27  */
28 
29 #include "tbf-queue-disc.h"
30 
31 #include "ns3/attribute.h"
32 #include "ns3/drop-tail-queue.h"
33 #include "ns3/enum.h"
34 #include "ns3/log.h"
35 #include "ns3/net-device-queue-interface.h"
36 #include "ns3/object-factory.h"
37 #include "ns3/simulator.h"
38 #include "ns3/uinteger.h"
39 
40 namespace ns3
41 {
42 
43 NS_LOG_COMPONENT_DEFINE("TbfQueueDisc");
44 
45 NS_OBJECT_ENSURE_REGISTERED(TbfQueueDisc);
46 
47 TypeId
49 {
50  static TypeId tid =
51  TypeId("ns3::TbfQueueDisc")
53  .SetGroupName("TrafficControl")
54  .AddConstructor<TbfQueueDisc>()
55  .AddAttribute("MaxSize",
56  "The max queue size",
57  QueueSizeValue(QueueSize("1000p")),
58  MakeQueueSizeAccessor(&QueueDisc::SetMaxSize, &QueueDisc::GetMaxSize),
59  MakeQueueSizeChecker())
60  .AddAttribute("Burst",
61  "Size of the first bucket in bytes",
62  UintegerValue(125000),
64  MakeUintegerChecker<uint32_t>())
65  .AddAttribute("Mtu",
66  "Size of the second bucket in bytes. If null, it is initialized"
67  " to the MTU of the receiving NetDevice (if any)",
68  UintegerValue(0),
70  MakeUintegerChecker<uint32_t>())
71  .AddAttribute("Rate",
72  "Rate at which tokens enter the first bucket in bps or Bps.",
73  DataRateValue(DataRate("125KB/s")),
74  MakeDataRateAccessor(&TbfQueueDisc::SetRate),
75  MakeDataRateChecker())
76  .AddAttribute("PeakRate",
77  "Rate at which tokens enter the second bucket in bps or Bps."
78  "If null, there is no second bucket",
79  DataRateValue(DataRate("0KB/s")),
80  MakeDataRateAccessor(&TbfQueueDisc::SetPeakRate),
81  MakeDataRateChecker())
82  .AddTraceSource("TokensInFirstBucket",
83  "Number of First Bucket Tokens in bytes",
85  "ns3::TracedValueCallback::Uint32")
86  .AddTraceSource("TokensInSecondBucket",
87  "Number of Second Bucket Tokens in bytes",
89  "ns3::TracedValueCallback::Uint32");
90 
91  return tid;
92 }
93 
96 {
97  NS_LOG_FUNCTION(this);
98 }
99 
101 {
102  NS_LOG_FUNCTION(this);
103 }
104 
105 void
107 {
108  NS_LOG_FUNCTION(this);
110 }
111 
112 void
113 TbfQueueDisc::SetBurst(uint32_t burst)
114 {
115  NS_LOG_FUNCTION(this << burst);
116  m_burst = burst;
117 }
118 
119 uint32_t
121 {
122  NS_LOG_FUNCTION(this);
123  return m_burst;
124 }
125 
126 void
127 TbfQueueDisc::SetMtu(uint32_t mtu)
128 {
129  NS_LOG_FUNCTION(this << mtu);
130  m_mtu = mtu;
131 }
132 
133 uint32_t
135 {
136  NS_LOG_FUNCTION(this);
137  return m_mtu;
138 }
139 
140 void
142 {
143  NS_LOG_FUNCTION(this << rate);
144  m_rate = rate;
145 }
146 
147 DataRate
149 {
150  NS_LOG_FUNCTION(this);
151  return m_rate;
152 }
153 
154 void
156 {
157  NS_LOG_FUNCTION(this << peakRate);
158  m_peakRate = peakRate;
159 }
160 
161 DataRate
163 {
164  NS_LOG_FUNCTION(this);
165  return m_peakRate;
166 }
167 
168 uint32_t
170 {
171  NS_LOG_FUNCTION(this);
172  return m_btokens;
173 }
174 
175 uint32_t
177 {
178  NS_LOG_FUNCTION(this);
179  return m_ptokens;
180 }
181 
182 bool
184 {
185  NS_LOG_FUNCTION(this << item);
186 
187  bool retval = GetQueueDiscClass(0)->GetQueueDisc()->Enqueue(item);
188 
189  // If Queue::Enqueue fails, QueueDisc::Drop is called by the child queue
190  // disc because QueueDisc::AddQueueDiscClass sets the drop callback
191 
192  NS_LOG_LOGIC("Current queue size: " << GetNPackets() << " packets, " << GetNBytes()
193  << " bytes");
194 
195  return retval;
196 }
197 
200 {
201  NS_LOG_FUNCTION(this);
202  Ptr<const QueueDiscItem> itemPeek = GetQueueDiscClass(0)->GetQueueDisc()->Peek();
203 
204  if (itemPeek)
205  {
206  uint32_t pktSize = itemPeek->GetSize();
207  NS_LOG_LOGIC("Next packet size " << pktSize);
208 
209  int64_t btoks = 0;
210  int64_t ptoks = 0;
211  Time now = Simulator::Now();
212 
213  double delta = (now - m_timeCheckPoint).GetSeconds();
214  NS_LOG_LOGIC("Time Difference delta " << delta);
215 
216  if (m_peakRate > DataRate("0bps"))
217  {
218  ptoks = m_ptokens + round(delta * (m_peakRate.GetBitRate() / 8));
219  if (ptoks > m_mtu)
220  {
221  ptoks = m_mtu;
222  }
223  NS_LOG_LOGIC("Number of ptokens we can consume " << ptoks);
224  NS_LOG_LOGIC("Required to dequeue next packet " << pktSize);
225  ptoks -= pktSize;
226  }
227 
228  btoks = m_btokens + round(delta * (m_rate.GetBitRate() / 8));
229 
230  if (btoks > m_burst)
231  {
232  btoks = m_burst;
233  }
234 
235  NS_LOG_LOGIC("Number of btokens we can consume " << btoks);
236  NS_LOG_LOGIC("Required to dequeue next packet " << pktSize);
237  btoks -= pktSize;
238 
239  if ((btoks | ptoks) >= 0) // else packet blocked
240  {
241  Ptr<QueueDiscItem> item = GetQueueDiscClass(0)->GetQueueDisc()->Dequeue();
242  if (!item)
243  {
244  NS_LOG_DEBUG("That's odd! Expecting the peeked packet, we got no packet.");
245  return item;
246  }
247 
248  m_timeCheckPoint = now;
249  m_btokens = btoks;
250  m_ptokens = ptoks;
251 
252  NS_LOG_LOGIC(m_btokens << " btokens and " << m_ptokens
253  << " ptokens after packet dequeue");
254  NS_LOG_LOGIC("Current queue size: " << GetNPackets() << " packets, " << GetNBytes()
255  << " bytes");
256 
257  return item;
258  }
259 
260  // the watchdog timer setup.
261  // A packet gets blocked if the above if() condition is not satisfied:
262  // either or both btoks and ptoks are negative. In that case, we have
263  // to schedule the waking of queue when enough tokens are available.
264  if (m_id.IsExpired())
265  {
266  NS_ASSERT_MSG(m_rate.GetBitRate() > 0, "Rate must be positive");
267  Time requiredDelayTime;
268  if (m_peakRate.GetBitRate() == 0)
269  {
270  NS_ASSERT_MSG(btoks < 0, "Logic error; btoks must be < 0 here");
271  requiredDelayTime = m_rate.CalculateBytesTxTime(-btoks);
272  }
273  else
274  {
275  if (btoks < 0 && ptoks >= 0)
276  {
277  requiredDelayTime = m_rate.CalculateBytesTxTime(-btoks);
278  }
279  else if (btoks >= 0 && ptoks < 0)
280  {
281  requiredDelayTime = m_peakRate.CalculateBytesTxTime(-ptoks);
282  }
283  else
284  {
285  requiredDelayTime = std::max(m_rate.CalculateBytesTxTime(-btoks),
287  }
288  }
289  NS_ASSERT_MSG(requiredDelayTime.GetSeconds() >= 0, "Negative time");
290  m_id = Simulator::Schedule(requiredDelayTime, &QueueDisc::Run, this);
291  NS_LOG_LOGIC("Waking Event Scheduled in " << requiredDelayTime.As(Time::S));
292  }
293  }
294  return nullptr;
295 }
296 
297 bool
299 {
300  NS_LOG_FUNCTION(this);
301  if (GetNInternalQueues() > 0)
302  {
303  NS_LOG_ERROR("TbfQueueDisc cannot have internal queues");
304  return false;
305  }
306 
307  if (GetNPacketFilters() > 0)
308  {
309  NS_LOG_ERROR("TbfQueueDisc cannot have packet filters");
310  return false;
311  }
312 
313  if (GetNQueueDiscClasses() == 0)
314  {
315  // create a FIFO queue disc
316  ObjectFactory factory;
317  factory.SetTypeId("ns3::FifoQueueDisc");
318  Ptr<QueueDisc> qd = factory.Create<QueueDisc>();
319 
320  if (!qd->SetMaxSize(GetMaxSize()))
321  {
322  NS_LOG_ERROR("Cannot set the max size of the child queue disc to that of TbfQueueDisc");
323  return false;
324  }
325  qd->Initialize();
326 
327  Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass>();
328  c->SetQueueDisc(qd);
330  }
331 
332  if (GetNQueueDiscClasses() != 1)
333  {
334  NS_LOG_ERROR("TbfQueueDisc needs 1 child queue disc");
335  return false;
336  }
337 
338  // This type of variable initialization would normally be done in
339  // InitializeParams (), but we want to use the value to subsequently
340  // check configuration of peak rate, so we move it forward here.
341  if (m_mtu == 0)
342  {
344  Ptr<NetDevice> dev;
345  // if the NetDeviceQueueInterface object is aggregated to a
346  // NetDevice, get the MTU of such NetDevice
347  if (ndqi && (dev = ndqi->GetObject<NetDevice>()))
348  {
349  m_mtu = dev->GetMtu();
350  }
351  }
352 
353  if (m_mtu == 0 && m_peakRate > DataRate("0bps"))
354  {
355  NS_LOG_ERROR(
356  "A non-null peak rate has been set, but the mtu is null. No packet will be dequeued");
357  return false;
358  }
359 
360  if (m_burst <= m_mtu)
361  {
362  NS_LOG_WARN("The size of the first bucket ("
363  << m_burst << ") should be "
364  << "greater than the size of the second bucket (" << m_mtu << ").");
365  }
366 
367  if (m_peakRate > DataRate("0bps") && m_peakRate <= m_rate)
368  {
369  NS_LOG_WARN("The rate for the second bucket ("
370  << m_peakRate << ") should be "
371  << "greater than the rate for the first bucket (" << m_rate << ").");
372  }
373 
374  return true;
375 }
376 
377 void
379 {
380  NS_LOG_FUNCTION(this);
381  // Token Buckets are full at the beginning.
382  m_btokens = m_burst;
383  m_ptokens = m_mtu;
384  // Initialising other variables to 0.
386  m_id = EventId();
387 }
388 
389 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:42
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:291
An identifier for simulation events.
Definition: event-id.h:55
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:69
Network layer to device interface.
Definition: net-device.h:98
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:184
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:624
uint32_t GetNPackets() const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:432
uint32_t GetNBytes() const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:439
Ptr< NetDeviceQueueInterface > GetNetDeviceQueueInterface() const
Definition: queue-disc.cc:538
void Run()
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets,...
Definition: queue-disc.cc:945
std::size_t GetNQueueDiscClasses() const
Get the number of queue disc classes.
Definition: queue-disc.cc:661
QueueSize GetMaxSize() const
Get the maximum size of the queue disc.
Definition: queue-disc.cc:446
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:654
std::size_t GetNPacketFilters() const
Get the number of packet filters.
Definition: queue-disc.cc:618
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
Definition: queue-disc.cc:474
std::size_t GetNInternalQueues() const
Get the number of internal queues.
Definition: queue-disc.cc:598
void DoDispose() override
Dispose of the object.
Definition: queue-disc.cc:376
Class for representing queue sizes.
Definition: queue-size.h:96
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
A TBF packet queue disc.
DataRate GetRate() const
Get the rate of the tokens entering the first bucket.
TbfQueueDisc()
TbfQueueDisc Constructor.
void SetBurst(uint32_t burst)
Set the size of the first bucket in bytes.
TracedValue< uint32_t > m_ptokens
Current number of tokens in second bucket.
Ptr< QueueDiscItem > DoDequeue() override
This function actually extracts a packet from the queue disc.
Time m_timeCheckPoint
Time check-point.
uint32_t m_mtu
Size of second bucket in bytes.
~TbfQueueDisc() override
Destructor.
void DoDispose() override
Dispose of the object.
bool DoEnqueue(Ptr< QueueDiscItem > item) override
This function actually enqueues a packet into the queue disc.
void SetPeakRate(DataRate peakRate)
Set the rate of the tokens entering the second bucket.
uint32_t m_burst
Size of first bucket in bytes.
DataRate m_rate
Rate at which tokens enter the first bucket.
EventId m_id
EventId of the scheduled queue waking event when enough tokens are available.
void InitializeParams() override
Initialize parameters (if any) before the first packet is enqueued.
DataRate GetPeakRate() const
Get the rate of the tokens entering the second bucket.
void SetRate(DataRate rate)
Set the rate of the tokens entering the first bucket.
void SetMtu(uint32_t mtu)
Set the size of the second bucket in bytes.
uint32_t GetBurst() const
Get the size of the first bucket in bytes.
uint32_t GetFirstBucketTokens() const
Get the current number of tokens inside the first bucket in bytes.
static TypeId GetTypeId()
Get the type ID.
bool CheckConfig() override
Check whether the current configuration is correct.
uint32_t GetSecondBucketTokens() const
Get the current number of tokens inside the second bucket in bytes.
uint32_t GetMtu() const
Get the size of the second bucket in bytes.
TracedValue< uint32_t > m_btokens
Current number of tokens in first bucket.
DataRate m_peakRate
Rate at which tokens enter the second bucket.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
@ S
second
Definition: nstime.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
QueueDiscSizePolicy
Enumeration of the available policies to handle the queue disc size.
Definition: queue-disc.h:107
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition: queue-disc.h:109
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
uint32_t pktSize
packet size used for the simulation (in bytes)