A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
net-device-queue-interface.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Stefano Avallone <stefano.avallone@.unina.it>
18 */
19#ifndef NET_DEVICE_QUEUE_INTERFACE_H
20#define NET_DEVICE_QUEUE_INTERFACE_H
21
22#include "ns3/callback.h"
23#include "ns3/log.h"
24#include "ns3/net-device.h"
25#include "ns3/object-factory.h"
26#include "ns3/object.h"
27#include "ns3/ptr.h"
28#include "ns3/simulator.h"
29
30#include <functional>
31#include <vector>
32
33namespace ns3
34{
35
36class QueueLimits;
37class NetDeviceQueueInterface;
38class QueueItem;
39
40/**
41 * \ingroup network
42 * \defgroup netdevice Network Device
43 */
44
45/**
46 * \ingroup netdevice
47 *
48 * \brief Network device transmission queue
49 *
50 * This class stores information about a single transmission queue
51 * of a network device that is exposed to queue discs. Such information
52 * includes the state of the transmission queue (whether it has been
53 * stopped or not) and data used by techniques such as Byte Queue Limits.
54 *
55 * This class roughly models the struct netdev_queue of Linux.
56 */
57class NetDeviceQueue : public Object
58{
59 public:
60 /**
61 * \brief Get the type ID.
62 * \return the object TypeId
63 */
64 static TypeId GetTypeId();
65
67 ~NetDeviceQueue() override;
68
69 /**
70 * Called by the device to start this device transmission queue.
71 * This is the analogous to the netif_tx_start_queue function of the Linux kernel.
72 */
73 virtual void Start();
74
75 /**
76 * Called by the device to stop this device transmission queue.
77 * This is the analogous to the netif_tx_stop_queue function of the Linux kernel.
78 */
79 virtual void Stop();
80
81 /**
82 * Called by the device to wake the queue disc associated with this
83 * device transmission queue. This is done by invoking the wake callback.
84 * This is the analogous to the netif_tx_wake_queue function of the Linux kernel.
85 */
86 virtual void Wake();
87
88 /**
89 * \brief Get the status of the device transmission queue.
90 * \return true if the device transmission queue is stopped.
91 *
92 * Called by queue discs to enquire about the status of a given transmission queue.
93 * This is the analogous to the netif_xmit_stopped function of the Linux kernel.
94 */
95 virtual bool IsStopped() const;
96
97 /**
98 * \brief Notify this NetDeviceQueue that the NetDeviceQueueInterface was
99 * aggregated to an object.
100 *
101 * \param ndqi the NetDeviceQueueInterface.
102 *
103 * This NetDeviceQueue stores a pointer to the NetDevice the NetDeviceQueueInterface
104 * was aggregated to.
105 */
107
108 /// Callback invoked by netdevices to wake upper layers
110
111 /**
112 * \brief Set the wake callback
113 * \param cb the callback to set
114 *
115 * Called by the traffic control layer to set the wake callback. The wake callback
116 * is invoked by the device whenever it is needed to "wake" the upper layers (i.e.,
117 * solicitate the queue disc associated with this transmission queue (in case of
118 * multi-queue aware queue discs) or to the network device (otherwise) to send
119 * packets down to the device).
120 */
121 virtual void SetWakeCallback(WakeCallback cb);
122
123 /**
124 * \brief Called by the netdevice to report the number of bytes queued to the device queue
125 * \param bytes number of bytes queued to the device queue
126 */
127 virtual void NotifyQueuedBytes(uint32_t bytes);
128
129 /**
130 * \brief Called by the netdevice to report the number of bytes it is going to transmit
131 * \param bytes number of bytes the device is going to transmit
132 */
133 virtual void NotifyTransmittedBytes(uint32_t bytes);
134
135 /**
136 * \brief Reset queue limits state
137 */
138 void ResetQueueLimits();
139
140 /**
141 * \brief Set queue limits to this queue
142 * \param ql the queue limits associated to this queue
143 */
145
146 /**
147 * \brief Get queue limits to this queue
148 * \return the queue limits associated to this queue
149 */
151
152 /**
153 * \brief Perform the actions required by flow control and dynamic queue
154 * limits when a packet is enqueued in the queue of a netdevice
155 *
156 * \param queue the device queue
157 * \param item the enqueued packet
158 *
159 * This method must be connected to the "Enqueue" traced callback of a Queue
160 * object (through a bound callback) in order for a netdevice to support
161 * flow control and dynamic queue limits.
162 */
163 template <typename QueueType>
164 void PacketEnqueued(QueueType* queue, Ptr<const typename QueueType::ItemType> item);
165
166 /**
167 * \brief Perform the actions required by flow control and dynamic queue
168 * limits when a packet is dequeued (or dropped after dequeue) from
169 * the queue of a netdevice
170 *
171 * \param queue the device queue
172 * \param item the dequeued packet
173 *
174 * This method must be connected to the "Dequeue" traced callback of a Queue
175 * object (through a bound callback) in order for
176 * a netdevice to support flow control and dynamic queue limits.
177 */
178 template <typename QueueType>
179 void PacketDequeued(QueueType* queue, Ptr<const typename QueueType::ItemType> item);
180
181 /**
182 * \brief Perform the actions required by flow control and dynamic queue
183 * limits when a packet is dropped before being enqueued in the queue
184 * of a netdevice (which likely indicates that the queue is full)
185 *
186 * \param queue the device queue
187 * \param item the dropped packet
188 *
189 * This method must be connected to the "DropBeforeEnqueue" traced callback
190 * of a Queue object (through a bound callback) in order for a netdevice to
191 * support flow control and dynamic queue limits.
192 */
193 template <typename QueueType>
194 void PacketDiscarded(QueueType* queue, Ptr<const typename QueueType::ItemType> item);
195
196 /**
197 * \brief Connect the traced callbacks of a queue to the methods providing support
198 * for flow control and dynamic queue limits. A queue can be any object providing:
199 * - "Enqueue", "Dequeue", "DropBeforeEnqueue" traces
200 * - an ItemType typedef for the type of stored items
201 * - GetCurrentSize and GetMaxSize methods
202 * \param queue the queue
203 */
204 template <typename QueueType>
206
207 private:
208 bool m_stoppedByDevice; //!< True if the queue has been stopped by the device
209 bool m_stoppedByQueueLimits; //!< True if the queue has been stopped by a queue limits object
210 Ptr<QueueLimits> m_queueLimits; //!< Queue limits object
211 WakeCallback m_wakeCallback; //!< Wake callback
212 Ptr<NetDevice> m_device; //!< the netdevice aggregated to the NetDeviceQueueInterface
213
214 NS_LOG_TEMPLATE_DECLARE; //!< redefinition of the log component
215};
216
217/**
218 * \ingroup netdevice
219 *
220 * \brief Network device transmission queue interface
221 *
222 * This interface is used by the traffic control layer and by the aggregated
223 * device to access the transmission queues of the device. Additionally, through
224 * this interface, traffic control aware netdevices can:
225 * - set the number of transmission queues
226 * - set the method used (by upper layers) to determine the transmission queue
227 * in which the netdevice would enqueue a given packet
228 * NetDevice helpers create this interface and aggregate it to the device.
229 */
231{
232 public:
233 /**
234 * \brief Get the type ID.
235 * \return the object TypeId
236 */
237 static TypeId GetTypeId();
238
239 /**
240 * \brief Constructor
241 */
243 ~NetDeviceQueueInterface() override;
244
245 /**
246 * \brief Get the i-th transmission queue of the device.
247 *
248 * \param i the index of the requested queue.
249 * \return the i-th transmission queue of the device.
250 *
251 * The index of the first transmission queue is zero.
252 */
253 Ptr<NetDeviceQueue> GetTxQueue(std::size_t i) const;
254
255 /**
256 * \brief Get the number of device transmission queues.
257 * \return the number of device transmission queues.
258 */
259 std::size_t GetNTxQueues() const;
260
261 /**
262 * \brief Set the type of device transmission queues to create.
263 * \param type type of device transmission queues to create.
264 *
265 * This method is called when the TxQueuesType attribute is set to create
266 * the corresponding type of device transmission queues. It cannot be
267 * called again afterwards.
268 */
269 void SetTxQueuesType(TypeId type);
270
271 /**
272 * \brief Set the number of device transmission queues to create.
273 * \param numTxQueues number of device transmission queues to create.
274 *
275 * This method is called when the NTxQueues attribute is set to create
276 * the corresponding number of device transmission queues. It cannot be
277 * called again afterwards.
278 */
279 void SetNTxQueues(std::size_t numTxQueues);
280
281 /// Callback invoked to determine the tx queue selected for a given packet
282 typedef std::function<std::size_t(Ptr<QueueItem>)> SelectQueueCallback;
283
284 /**
285 * \brief Set the select queue callback.
286 * \param cb the callback to set.
287 *
288 * This method is called to set the select queue callback, i.e., the
289 * method used to select a device transmission queue for a given packet.
290 */
292
293 /**
294 * \brief Get the select queue callback.
295 * \return the select queue callback.
296 *
297 * Called by the traffic control layer to get the select queue callback set
298 * by a multi-queue device.
299 */
301
302 protected:
303 /**
304 * \brief Dispose of the object
305 */
306 void DoDispose() override;
307 /**
308 * \brief Notify that an object was aggregated
309 */
310 void NotifyNewAggregate() override;
311
312 private:
313 ObjectFactory m_txQueues; //!< Device transmission queues TypeId
314 std::vector<Ptr<NetDeviceQueue>> m_txQueuesVector; //!< Device transmission queues
315 SelectQueueCallback m_selectQueueCallback; //!< Select queue callback
316};
317
318/**
319 * Implementation of the templates declared above.
320 */
321
322template <typename QueueType>
323void
325{
326 NS_ASSERT(queue);
327
328 queue->TraceConnectWithoutContext(
329 "Enqueue",
330 MakeCallback(&NetDeviceQueue::PacketEnqueued<QueueType>, this).Bind(PeekPointer(queue)));
331 queue->TraceConnectWithoutContext(
332 "Dequeue",
333 MakeCallback(&NetDeviceQueue::PacketDequeued<QueueType>, this).Bind(PeekPointer(queue)));
334 queue->TraceConnectWithoutContext(
335 "DropBeforeEnqueue",
336 MakeCallback(&NetDeviceQueue::PacketDiscarded<QueueType>, this).Bind(PeekPointer(queue)));
337}
338
339template <typename QueueType>
340void
342{
343 NS_LOG_FUNCTION(this << queue << item);
344
345 // Inform BQL
346 NotifyQueuedBytes(item->GetSize());
347
348 NS_ASSERT_MSG(m_device, "Aggregated NetDevice not set");
349 // After enqueuing a packet, we need to check whether the queue is able to
350 // store another packet. If not, we stop the queue
351
352 if (queue->WouldOverflow(1, m_device->GetMtu()))
353 {
354 NS_LOG_DEBUG("The device queue is being stopped (" << queue->GetCurrentSize()
355 << " inside)");
356 Stop();
357 }
358}
359
360template <typename QueueType>
361void
363{
364 NS_LOG_FUNCTION(this << queue << item);
365 NS_ASSERT_MSG(m_device, "Aggregated NetDevice not set");
366
367 Simulator::ScheduleNow([=, this]() {
368 // Inform BQL
369 NotifyTransmittedBytes(item->GetSize());
370
371 // After dequeuing a packet, if there is room for another packet we
372 // call Wake () that ensures that the queue is not stopped and restarts
373 // the queue disc if the queue was stopped
374
375 if (!queue->WouldOverflow(1, m_device->GetMtu()))
376 {
377 Wake();
378 }
379 });
380}
381
382template <typename QueueType>
383void
385{
386 NS_LOG_FUNCTION(this << queue << item);
387
388 // This method is called when a packet is discarded before being enqueued in the
389 // device queue, likely because the queue is full. This should not happen if the
390 // device correctly stops the queue. Anyway, stop the tx queue, so that the upper
391 // layers do not send packets until there is room in the queue again.
392
393 NS_LOG_ERROR("BUG! No room in the device queue for the received packet! ("
394 << queue->GetCurrentSize() << " inside)");
395
396 Stop();
397}
398
399} // namespace ns3
400
401#endif /* NET_DEVICE_QUEUE_INTERFACE_H */
Callback template class.
Definition: callback.h:438
Network device transmission queue.
bool m_stoppedByQueueLimits
True if the queue has been stopped by a queue limits object.
void ConnectQueueTraces(Ptr< QueueType > queue)
Connect the traced callbacks of a queue to the methods providing support for flow control and dynamic...
virtual void Stop()
Called by the device to stop this device transmission queue.
void NotifyAggregatedObject(Ptr< NetDeviceQueueInterface > ndqi)
Notify this NetDeviceQueue that the NetDeviceQueueInterface was aggregated to an object.
void PacketDiscarded(QueueType *queue, Ptr< const typename QueueType::ItemType > item)
Perform the actions required by flow control and dynamic queue limits when a packet is dropped before...
Ptr< QueueLimits > GetQueueLimits()
Get queue limits to this queue.
Ptr< QueueLimits > m_queueLimits
Queue limits object.
virtual void Wake()
Called by the device to wake the queue disc associated with this device transmission queue.
virtual bool IsStopped() const
Get the status of the device transmission queue.
void SetQueueLimits(Ptr< QueueLimits > ql)
Set queue limits to this queue.
NS_LOG_TEMPLATE_DECLARE
redefinition of the log component
void PacketDequeued(QueueType *queue, Ptr< const typename QueueType::ItemType > item)
Perform the actions required by flow control and dynamic queue limits when a packet is dequeued (or d...
void ResetQueueLimits()
Reset queue limits state.
virtual void Start()
Called by the device to start this device transmission queue.
virtual void NotifyTransmittedBytes(uint32_t bytes)
Called by the netdevice to report the number of bytes it is going to transmit.
virtual void NotifyQueuedBytes(uint32_t bytes)
Called by the netdevice to report the number of bytes queued to the device queue.
Ptr< NetDevice > m_device
the netdevice aggregated to the NetDeviceQueueInterface
WakeCallback m_wakeCallback
Wake callback.
Callback< void > WakeCallback
Callback invoked by netdevices to wake upper layers.
bool m_stoppedByDevice
True if the queue has been stopped by the device.
static TypeId GetTypeId()
Get the type ID.
virtual void SetWakeCallback(WakeCallback cb)
Set the wake callback.
void PacketEnqueued(QueueType *queue, Ptr< const typename QueueType::ItemType > item)
Perform the actions required by flow control and dynamic queue limits when a packet is enqueued in th...
Network device transmission queue interface.
SelectQueueCallback m_selectQueueCallback
Select queue callback.
std::vector< Ptr< NetDeviceQueue > > m_txQueuesVector
Device transmission queues.
std::size_t GetNTxQueues() const
Get the number of device transmission queues.
Ptr< NetDeviceQueue > GetTxQueue(std::size_t i) const
Get the i-th transmission queue of the device.
std::function< std::size_t(Ptr< QueueItem >)> SelectQueueCallback
Callback invoked to determine the tx queue selected for a given packet.
ObjectFactory m_txQueues
Device transmission queues TypeId.
void SetSelectQueueCallback(SelectQueueCallback cb)
Set the select queue callback.
void DoDispose() override
Dispose of the object.
SelectQueueCallback GetSelectQueueCallback() const
Get the select queue callback.
void SetTxQueuesType(TypeId type)
Set the type of device transmission queues to create.
void SetNTxQueues(std::size_t numTxQueues)
Set the number of device transmission queues to create.
void NotifyNewAggregate() override
Notify that an object was aggregated.
static TypeId GetTypeId()
Get the type ID.
Instantiate subclasses of ns3::Object.
A base class which provides memory management and object aggregation.
Definition: object.h:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
a unique identifier for an interface.
Definition: type-id.h:59
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:454
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:706