A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * TBF, The Token Bucket Filter Queueing discipline
8 *
9 * This implementation is based on linux kernel code by
10 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11 * Dmitry Torokhov <dtor@mail.ru> - allow attaching inner qdiscs -
12 * original idea by Martin Devera
13 *
14 * Implemented in ns-3 by: Surya Seetharaman <suryaseetharaman.9@gmail.com>
15 * Stefano Avallone <stavallo@unina.it>
16 */
17
18#include "tbf-queue-disc.h"
19
20#include "ns3/attribute.h"
21#include "ns3/drop-tail-queue.h"
22#include "ns3/enum.h"
23#include "ns3/log.h"
24#include "ns3/net-device-queue-interface.h"
25#include "ns3/object-factory.h"
26#include "ns3/simulator.h"
27#include "ns3/uinteger.h"
28
29namespace ns3
30{
31
32NS_LOG_COMPONENT_DEFINE("TbfQueueDisc");
33
34NS_OBJECT_ENSURE_REGISTERED(TbfQueueDisc);
35
36TypeId
38{
39 static TypeId tid =
40 TypeId("ns3::TbfQueueDisc")
42 .SetGroupName("TrafficControl")
43 .AddConstructor<TbfQueueDisc>()
44 .AddAttribute("MaxSize",
45 "The max queue size",
46 QueueSizeValue(QueueSize("1000p")),
49 .AddAttribute("Burst",
50 "Size of the first bucket in bytes",
51 UintegerValue(125000),
54 .AddAttribute("Mtu",
55 "Size of the second bucket in bytes. If null, it is initialized"
56 " to the MTU of the receiving NetDevice (if any)",
60 .AddAttribute("Rate",
61 "Rate at which tokens enter the first bucket in bps or Bps.",
62 DataRateValue(DataRate("125KB/s")),
65 .AddAttribute("PeakRate",
66 "Rate at which tokens enter the second bucket in bps or Bps."
67 "If null, there is no second bucket",
68 DataRateValue(DataRate("0KB/s")),
71 .AddTraceSource("TokensInFirstBucket",
72 "Number of First Bucket Tokens in bytes",
74 "ns3::TracedValueCallback::Uint32")
75 .AddTraceSource("TokensInSecondBucket",
76 "Number of Second Bucket Tokens in bytes",
78 "ns3::TracedValueCallback::Uint32");
79
80 return tid;
81}
82
88
93
94void
100
101void
103{
104 NS_LOG_FUNCTION(this << burst);
105 m_burst = burst;
106}
107
110{
111 NS_LOG_FUNCTION(this);
112 return m_burst;
113}
114
115void
117{
118 NS_LOG_FUNCTION(this << mtu);
119 m_mtu = mtu;
120}
121
124{
125 NS_LOG_FUNCTION(this);
126 return m_mtu;
127}
128
129void
131{
132 NS_LOG_FUNCTION(this << rate);
133 m_rate = rate;
134}
135
138{
139 NS_LOG_FUNCTION(this);
140 return m_rate;
141}
142
143void
145{
146 NS_LOG_FUNCTION(this << peakRate);
147 m_peakRate = peakRate;
148}
149
152{
153 NS_LOG_FUNCTION(this);
154 return m_peakRate;
155}
156
159{
160 NS_LOG_FUNCTION(this);
161 return m_btokens;
162}
163
166{
167 NS_LOG_FUNCTION(this);
168 return m_ptokens;
169}
170
171bool
173{
174 NS_LOG_FUNCTION(this << item);
175
176 bool retval = GetQueueDiscClass(0)->GetQueueDisc()->Enqueue(item);
177
178 // If Queue::Enqueue fails, QueueDisc::Drop is called by the child queue
179 // disc because QueueDisc::AddQueueDiscClass sets the drop callback
180
181 NS_LOG_LOGIC("Current queue size: " << GetNPackets() << " packets, " << GetNBytes()
182 << " bytes");
183
184 return retval;
185}
186
189{
190 NS_LOG_FUNCTION(this);
191 Ptr<const QueueDiscItem> itemPeek = GetQueueDiscClass(0)->GetQueueDisc()->Peek();
192
193 if (itemPeek)
194 {
195 uint32_t pktSize = itemPeek->GetSize();
196 NS_LOG_LOGIC("Next packet size " << pktSize);
197
198 int64_t btoks = 0;
199 int64_t ptoks = 0;
200 Time now = Simulator::Now();
201
202 double delta = (now - m_timeCheckPoint).GetSeconds();
203 NS_LOG_LOGIC("Time Difference delta " << delta);
204
205 if (m_peakRate > DataRate("0bps"))
206 {
207 ptoks = m_ptokens + round(delta * (m_peakRate.GetBitRate() / 8));
208 if (ptoks > m_mtu)
209 {
210 ptoks = m_mtu;
211 }
212 NS_LOG_LOGIC("Number of ptokens we can consume " << ptoks);
213 NS_LOG_LOGIC("Required to dequeue next packet " << pktSize);
214 ptoks -= pktSize;
215 }
216
217 btoks = m_btokens + round(delta * (m_rate.GetBitRate() / 8));
218
219 if (btoks > m_burst)
220 {
221 btoks = m_burst;
222 }
223
224 NS_LOG_LOGIC("Number of btokens we can consume " << btoks);
225 NS_LOG_LOGIC("Required to dequeue next packet " << pktSize);
226 btoks -= pktSize;
227
228 if ((btoks | ptoks) >= 0) // else packet blocked
229 {
230 Ptr<QueueDiscItem> item = GetQueueDiscClass(0)->GetQueueDisc()->Dequeue();
231 if (!item)
232 {
233 NS_LOG_DEBUG("That's odd! Expecting the peeked packet, we got no packet.");
234 return item;
235 }
236
237 m_timeCheckPoint = now;
238 m_btokens = btoks;
239 m_ptokens = ptoks;
240
241 NS_LOG_LOGIC(m_btokens << " btokens and " << m_ptokens
242 << " ptokens after packet dequeue");
243 NS_LOG_LOGIC("Current queue size: " << GetNPackets() << " packets, " << GetNBytes()
244 << " bytes");
245
246 return item;
247 }
248
249 // the watchdog timer setup.
250 // A packet gets blocked if the above if() condition is not satisfied:
251 // either or both btoks and ptoks are negative. In that case, we have
252 // to schedule the waking of queue when enough tokens are available.
253 if (m_id.IsExpired())
254 {
255 NS_ASSERT_MSG(m_rate.GetBitRate() > 0, "Rate must be positive");
256 Time requiredDelayTime;
257 if (m_peakRate.GetBitRate() == 0)
258 {
259 NS_ASSERT_MSG(btoks < 0, "Logic error; btoks must be < 0 here");
260 requiredDelayTime = m_rate.CalculateBytesTxTime(-btoks);
261 }
262 else
263 {
264 if (btoks < 0 && ptoks >= 0)
265 {
266 requiredDelayTime = m_rate.CalculateBytesTxTime(-btoks);
267 }
268 else if (btoks >= 0 && ptoks < 0)
269 {
270 requiredDelayTime = m_peakRate.CalculateBytesTxTime(-ptoks);
271 }
272 else
273 {
274 requiredDelayTime = std::max(m_rate.CalculateBytesTxTime(-btoks),
276 }
277 }
278 NS_ASSERT_MSG(requiredDelayTime.GetSeconds() >= 0, "Negative time");
279 m_id = Simulator::Schedule(requiredDelayTime, &QueueDisc::Run, this);
280 NS_LOG_LOGIC("Waking Event Scheduled in " << requiredDelayTime.As(Time::S));
281 }
282 }
283 return nullptr;
284}
285
286bool
288{
289 NS_LOG_FUNCTION(this);
290 if (GetNInternalQueues() > 0)
291 {
292 NS_LOG_ERROR("TbfQueueDisc cannot have internal queues");
293 return false;
294 }
295
296 if (GetNPacketFilters() > 0)
297 {
298 NS_LOG_ERROR("TbfQueueDisc cannot have packet filters");
299 return false;
300 }
301
302 if (GetNQueueDiscClasses() == 0)
303 {
304 // create a FIFO queue disc
305 ObjectFactory factory;
306 factory.SetTypeId("ns3::FifoQueueDisc");
307 Ptr<QueueDisc> qd = factory.Create<QueueDisc>();
308
309 if (!qd->SetMaxSize(GetMaxSize()))
310 {
311 NS_LOG_ERROR("Cannot set the max size of the child queue disc to that of TbfQueueDisc");
312 return false;
313 }
314 qd->Initialize();
315
317 c->SetQueueDisc(qd);
319 }
320
321 if (GetNQueueDiscClasses() != 1)
322 {
323 NS_LOG_ERROR("TbfQueueDisc needs 1 child queue disc");
324 return false;
325 }
326
327 // This type of variable initialization would normally be done in
328 // InitializeParams (), but we want to use the value to subsequently
329 // check configuration of peak rate, so we move it forward here.
330 if (m_mtu == 0)
331 {
333 Ptr<NetDevice> dev;
334 // if the NetDeviceQueueInterface object is aggregated to a
335 // NetDevice, get the MTU of such NetDevice
336 if (ndqi && (dev = ndqi->GetObject<NetDevice>()))
337 {
338 m_mtu = dev->GetMtu();
339 }
340 }
341
342 if (m_mtu == 0 && m_peakRate > DataRate("0bps"))
343 {
345 "A non-null peak rate has been set, but the mtu is null. No packet will be dequeued");
346 return false;
347 }
348
349 if (m_burst <= m_mtu)
350 {
351 NS_LOG_WARN("The size of the first bucket ("
352 << m_burst << ") should be "
353 << "greater than the size of the second bucket (" << m_mtu << ").");
354 }
355
356 if (m_peakRate > DataRate("0bps") && m_peakRate <= m_rate)
357 {
358 NS_LOG_WARN("The rate for the second bucket ("
359 << m_peakRate << ") should be "
360 << "greater than the rate for the first bucket (" << m_rate << ").");
361 }
362
363 return true;
364}
365
366void
368{
369 NS_LOG_FUNCTION(this);
370 // Token Buckets are full at the beginning.
373 // Initialising other variables to 0.
375 m_id = EventId();
376}
377
378} // namespace ns3
Class for representing data rates.
Definition data-rate.h:78
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition data-rate.cc:234
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition data-rate.cc:220
An identifier for simulation events.
Definition event-id.h:45
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition event-id.cc:58
Network layer to device interface.
Definition net-device.h:87
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.
Smart pointer class similar to boost::intrusive_ptr.
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition queue-disc.h:173
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
uint32_t GetNPackets() const
Get the number of packets stored by the queue disc.
uint32_t GetNBytes() const
Get the amount of bytes stored by the queue disc.
Ptr< NetDeviceQueueInterface > GetNetDeviceQueueInterface() const
void Run()
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets,...
std::size_t GetNQueueDiscClasses() const
Get the number of queue disc classes.
QueueSize GetMaxSize() const
Get the maximum size of the queue disc.
Ptr< QueueDiscClass > GetQueueDiscClass(std::size_t i) const
Get the i-th queue disc class.
std::size_t GetNPacketFilters() const
Get the number of packet filters.
bool SetMaxSize(QueueSize size)
Set the maximum size of the queue disc.
std::size_t GetNInternalQueues() const
Get the number of internal queues.
void DoDispose() override
Dispose of the object.
Class for representing queue sizes.
Definition queue-size.h:85
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
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:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#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:75
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
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:96
@ SINGLE_CHILD_QUEUE_DISC
Used by queue discs with single child queue disc.
Definition queue-disc.h:98
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeQueueSizeAccessor(T1 a1)
Definition queue-size.h:210
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeDataRateAccessor(T1 a1)
Definition data-rate.h:285
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeDataRateChecker()
Definition data-rate.cc:20
Ptr< const AttributeChecker > MakeQueueSizeChecker()
Definition queue-size.cc:18
uint32_t pktSize
packet size used for the simulation (in bytes)