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
40namespace ns3 {
41
42NS_LOG_COMPONENT_DEFINE ("TbfQueueDisc");
43
44NS_OBJECT_ENSURE_REGISTERED (TbfQueueDisc);
45
47{
48 static TypeId tid = TypeId ("ns3::TbfQueueDisc")
50 .SetGroupName ("TrafficControl")
51 .AddConstructor<TbfQueueDisc> ()
52 .AddAttribute ("MaxSize",
53 "The max queue size",
54 QueueSizeValue (QueueSize ("1000p")),
55 MakeQueueSizeAccessor (&QueueDisc::SetMaxSize,
57 MakeQueueSizeChecker ())
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 receiving 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")),
72 MakeDataRateAccessor (&TbfQueueDisc::SetRate),
73 MakeDataRateChecker ())
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")),
78 MakeDataRateAccessor (&TbfQueueDisc::SetPeakRate),
79 MakeDataRateChecker ())
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
104void
106{
107 NS_LOG_FUNCTION (this);
109}
110
111void
113{
114 NS_LOG_FUNCTION (this << burst);
115 m_burst = burst;
116}
117
120{
121 NS_LOG_FUNCTION (this);
122 return m_burst;
123}
124
125void
127{
128 NS_LOG_FUNCTION (this << mtu);
129 m_mtu = mtu;
130}
131
134{
135 NS_LOG_FUNCTION (this);
136 return m_mtu;
137}
138
139void
141{
142 NS_LOG_FUNCTION (this << rate);
143 m_rate = rate;
144}
145
148{
149 NS_LOG_FUNCTION (this);
150 return m_rate;
151}
152
153void
155{
156 NS_LOG_FUNCTION (this << peakRate);
157 m_peakRate = peakRate;
158}
159
162{
163 NS_LOG_FUNCTION (this);
164 return m_peakRate;
165}
166
169{
170 NS_LOG_FUNCTION (this);
171 return m_btokens;
172}
173
176{
177 NS_LOG_FUNCTION (this);
178 return m_ptokens;
179}
180
181bool
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 Ptr<const QueueDiscItem> itemPeek = GetQueueDiscClass (0)->GetQueueDisc ()->Peek ();
201
202 if (itemPeek)
203 {
204 uint32_t pktSize = itemPeek->GetSize ();
205 NS_LOG_LOGIC ("Next packet size " << pktSize);
206
207 int64_t btoks = 0;
208 int64_t ptoks = 0;
209 Time now = Simulator::Now ();
210
211 double delta = (now - m_timeCheckPoint).GetSeconds ();
212 NS_LOG_LOGIC ("Time Difference delta " << delta);
213
214 if (m_peakRate > DataRate ("0bps"))
215 {
216 ptoks = m_ptokens + round (delta * (m_peakRate.GetBitRate () / 8));
217 if (ptoks > m_mtu)
218 {
219 ptoks = m_mtu;
220 }
221 NS_LOG_LOGIC ("Number of ptokens we can consume " << ptoks);
222 NS_LOG_LOGIC ("Required to dequeue next packet " << pktSize);
223 ptoks -= pktSize;
224 }
225
226 btoks = m_btokens + round (delta * (m_rate.GetBitRate () / 8));
227
228 if (btoks > m_burst)
229 {
230 btoks = m_burst;
231 }
232
233 NS_LOG_LOGIC ("Number of btokens we can consume " << btoks);
234 NS_LOG_LOGIC ("Required to dequeue next packet " << pktSize);
235 btoks -= pktSize;
236
237 if ((btoks|ptoks) >= 0) // else packet blocked
238 {
239 Ptr<QueueDiscItem> item = GetQueueDiscClass (0)->GetQueueDisc ()->Dequeue ();
240 if (!item)
241 {
242 NS_LOG_DEBUG ("That's odd! Expecting the peeked packet, we got no packet.");
243 return item;
244 }
245
246 m_timeCheckPoint = now;
247 m_btokens = btoks;
248 m_ptokens = ptoks;
249
250 NS_LOG_LOGIC (m_btokens << " btokens and " << m_ptokens << " ptokens after packet dequeue");
251 NS_LOG_LOGIC ("Current queue size: " << GetNPackets () << " packets, " << GetNBytes () << " bytes");
252
253 return item;
254 }
255
256 // the watchdog timer setup.
257 // A packet gets blocked if the above if() condition is not satisfied:
258 // either or both btoks and ptoks are negative. In that case, we have
259 // to schedule the waking of queue when enough tokens are available.
260 if (m_id.IsExpired () == true)
261 {
262 NS_ASSERT_MSG (m_rate.GetBitRate () > 0, "Rate must be positive");
263 Time requiredDelayTime;
264 if (m_peakRate.GetBitRate () == 0)
265 {
266 NS_ASSERT_MSG (btoks < 0, "Logic error; btoks must be < 0 here");
267 requiredDelayTime = m_rate.CalculateBytesTxTime (-btoks);
268 }
269 else
270 {
271 if (btoks < 0 && ptoks >= 0)
272 {
273 requiredDelayTime = m_rate.CalculateBytesTxTime (-btoks);
274 }
275 else if (btoks >= 0 && ptoks < 0)
276 {
277 requiredDelayTime = m_peakRate.CalculateBytesTxTime (-ptoks);
278 }
279 else
280 {
281 requiredDelayTime = std::max (m_rate.CalculateBytesTxTime (-btoks),
283 }
284
285 }
286 NS_ASSERT_MSG (requiredDelayTime.GetSeconds () >= 0, "Negative time");
287 m_id = Simulator::Schedule (requiredDelayTime, &QueueDisc::Run, this);
288 NS_LOG_LOGIC("Waking Event Scheduled in " << requiredDelayTime.As (Time::S));
289 }
290 }
291 return 0;
292}
293
294bool
296{
297 NS_LOG_FUNCTION (this);
298 if (GetNInternalQueues () > 0)
299 {
300 NS_LOG_ERROR ("TbfQueueDisc cannot have internal queues");
301 return false;
302 }
303
304 if (GetNPacketFilters () > 0)
305 {
306 NS_LOG_ERROR ("TbfQueueDisc cannot have packet filters");
307 return false;
308 }
309
310 if (GetNQueueDiscClasses () == 0)
311 {
312 // create a FIFO queue disc
313 ObjectFactory factory;
314 factory.SetTypeId ("ns3::FifoQueueDisc");
315 Ptr<QueueDisc> qd = factory.Create<QueueDisc> ();
316
317 if (!qd->SetMaxSize (GetMaxSize ()))
318 {
319 NS_LOG_ERROR ("Cannot set the max size of the child queue disc to that of TbfQueueDisc");
320 return false;
321 }
322 qd->Initialize ();
323
324 Ptr<QueueDiscClass> c = CreateObject<QueueDiscClass> ();
325 c->SetQueueDisc (qd);
327 }
328
329 if (GetNQueueDiscClasses () != 1)
330 {
331 NS_LOG_ERROR ("TbfQueueDisc needs 1 child queue disc");
332 return false;
333 }
334
335 // This type of variable initialization would normally be done in
336 // InitializeParams (), but we want to use the value to subsequently
337 // check configuration of peak rate, so we move it forward here.
338 if (m_mtu == 0)
339 {
341 Ptr<NetDevice> dev;
342 // if the NetDeviceQueueInterface object is aggregated to a
343 // NetDevice, get the MTU of such NetDevice
344 if (ndqi && (dev = ndqi->GetObject<NetDevice> ()))
345 {
346 m_mtu = dev->GetMtu ();
347 }
348 }
349
350 if (m_mtu == 0 && m_peakRate > DataRate ("0bps"))
351 {
352 NS_LOG_ERROR ("A non-null peak rate has been set, but the mtu is null. No packet will be dequeued");
353 return false;
354 }
355
356 if (m_burst <= m_mtu)
357 {
358 NS_LOG_WARN ("The size of the first bucket (" << m_burst << ") should be "
359 << "greater than the size of the second bucket (" << m_mtu << ").");
360 }
361
362 if (m_peakRate > DataRate ("0bps") && m_peakRate <= m_rate)
363 {
364 NS_LOG_WARN ("The rate for the second bucket (" << m_peakRate << ") should be "
365 << "greater than the rate for the first bucket (" << m_rate << ").");
366 }
367
368 return true;
369}
370
371void
373{
374 NS_LOG_FUNCTION (this);
375 // Token Buckets are full at the beginning.
378 // Initialising other variables to 0.
380 m_id = EventId ();
381}
382
383} // namespace ns3
#define max(a, b)
Definition: 80211b.c:43
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition: data-rate.cc:275
AttributeValue implementation for DataRate.
An identifier for simulation events.
Definition: event-id.h:54
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:65
Network layer to device interface.
Definition: net-device.h:96
Instantiate subclasses of ns3::Object.
Ptr< Object > Create(void) 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(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:181
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:632
uint32_t GetNBytes(void) const
Get the amount of bytes stored by the queue disc.
Definition: queue-disc.cc:445
QueueSize GetMaxSize(void) const
Get the maximum size of the queue disc.
Definition: queue-disc.cc:452
void Run(void)
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets,...
Definition: queue-disc.cc:953
Ptr< NetDeviceQueueInterface > GetNetDeviceQueueInterface(void) const
Definition: queue-disc.cc:544
std::size_t GetNPacketFilters(void) const
Get the number of packet filters.
Definition: queue-disc.cc:626
uint32_t GetNPackets(void) const
Get the number of packets stored by the queue disc.
Definition: queue-disc.cc:438
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
Definition: queue-disc.cc:660
std::size_t GetNQueueDiscClasses(void) const
Get the number of queue disc classes.
Definition: queue-disc.cc:667
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
Definition: queue-disc.cc:480
virtual void DoDispose(void)
Dispose of the object.
Definition: queue-disc.cc:382
std::size_t GetNInternalQueues(void) const
Get the number of internal queues.
Definition: queue-disc.cc:606
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:555
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
A TBF packet queue disc.
DataRate GetPeakRate(void) const
Get the rate of the tokens entering the second bucket.
virtual bool CheckConfig(void)
Check whether the current configuration is correct.
TbfQueueDisc()
TbfQueueDisc Constructor.
void SetBurst(uint32_t burst)
Set the size of the first bucket in bytes.
virtual ~TbfQueueDisc()
Destructor.
virtual void InitializeParams(void)
Initialize parameters (if any) before the first packet is enqueued.
TracedValue< uint32_t > m_ptokens
Current number of tokens in second bucket.
Time m_timeCheckPoint
Time check-point.
uint32_t m_mtu
Size of second bucket in bytes.
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.
static TypeId GetTypeId(void)
Get the type ID.
DataRate GetRate(void) const
Get the rate of the tokens entering the first bucket.
uint32_t GetSecondBucketTokens(void) const
Get the current number of tokens inside the second bucket in bytes.
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.
virtual bool DoEnqueue(Ptr< QueueDiscItem > item)
This function actually enqueues a packet into the queue disc.
virtual void DoDispose(void)
Dispose of the object.
virtual Ptr< QueueDiscItem > DoDequeue(void)
This function actually extracts a packet from the queue disc.
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.
uint32_t GetBurst(void) const
Get the size of the first bucket in bytes.
DataRate m_peakRate
Rate at which tokens enter the second bucket.
uint32_t GetFirstBucketTokens(void) const
Get the current number of tokens inside the first bucket in bytes.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
@ S
second
Definition: nstime.h:115
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:418
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#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:88
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:258
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:206
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:274
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:290
#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:266
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
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:104
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition: queue-disc.h:106
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:90