A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
traffic-control-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "ns3/abort.h"
12#include "ns3/log.h"
13#include "ns3/net-device-queue-interface.h"
14#include "ns3/pointer.h"
15#include "ns3/queue-limits.h"
16#include "ns3/traffic-control-layer.h"
17#include "ns3/uinteger.h"
18
19namespace ns3
20{
21
22NS_LOG_COMPONENT_DEFINE("TrafficControlHelper");
23
28
29void
34
35void
40
41uint16_t
43{
44 m_queueDiscClassesFactory.push_back(factory);
45 return static_cast<uint16_t>(m_queueDiscClassesFactory.size() - 1);
46}
47
48void
49QueueDiscFactory::SetChildQueueDisc(uint16_t classId, uint16_t handle)
50{
52 "Cannot attach a queue disc to a non existing class");
53 m_classIdChildHandleMap[classId] = handle;
54}
55
58{
59 // create the queue disc
61
62 // create and add the internal queues
63 for (auto i = m_internalQueuesFactory.begin(); i != m_internalQueuesFactory.end(); i++)
64 {
65 qd->AddInternalQueue(i->Create<QueueDisc::InternalQueue>());
66 }
67
68 // create and add the packet filters
69 for (auto i = m_packetFiltersFactory.begin(); i != m_packetFiltersFactory.end(); i++)
70 {
71 qd->AddPacketFilter(i->Create<PacketFilter>());
72 }
73
74 // create and add the queue disc classes
75 for (std::size_t i = 0; i < m_queueDiscClassesFactory.size(); i++)
76 {
77 // the class ID is given by the index i of the vector
79 "Cannot create a queue disc class with no attached queue disc");
80
81 uint16_t handle = m_classIdChildHandleMap[i];
82 NS_ABORT_MSG_IF(handle >= queueDiscs.size() || !queueDiscs[handle],
83 "A queue disc with handle " << handle << " has not been created yet");
84
85 m_queueDiscClassesFactory[i].Set("QueueDisc", PointerValue(queueDiscs[handle]));
86 qd->AddQueueDiscClass(m_queueDiscClassesFactory[i].Create<QueueDiscClass>());
87 }
88
89 return qd;
90}
91
95
97TrafficControlHelper::Default(std::size_t nTxQueues)
98{
99 NS_LOG_FUNCTION(nTxQueues);
100 NS_ABORT_MSG_IF(nTxQueues == 0, "The device must have at least one queue");
102
103 if (nTxQueues == 1)
104 {
105 helper.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
106 }
107 else
108 {
109 uint16_t handle = helper.SetRootQueueDisc("ns3::MqQueueDisc");
110 ClassIdList cls = helper.AddQueueDiscClasses(handle, nTxQueues, "ns3::QueueDiscClass");
111 helper.AddChildQueueDiscs(handle, cls, "ns3::FqCoDelQueueDisc");
112 }
113 return helper;
114}
115
116uint16_t
118{
120 "A root queue disc has been already added to this factory");
121
122 m_queueDiscFactory.emplace_back(factory);
123 return 0;
124}
125
126void
127TrafficControlHelper::DoAddInternalQueues(uint16_t handle, uint16_t count, ObjectFactory factory)
128{
129 NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
130 "A queue disc with handle " << handle << " does not exist");
131
132 for (int i = 0; i < count; i++)
133 {
134 m_queueDiscFactory[handle].AddInternalQueue(factory);
135 }
136}
137
138void
140{
141 NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
142 "A queue disc with handle " << handle << " does not exist");
143
144 m_queueDiscFactory[handle].AddPacketFilter(factory);
145}
146
148TrafficControlHelper::DoAddQueueDiscClasses(uint16_t handle, uint16_t count, ObjectFactory factory)
149{
150 NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
151 "A queue disc with handle " << handle << " does not exist");
152
154 uint16_t classId;
155
156 for (int i = 0; i < count; i++)
157 {
158 classId = m_queueDiscFactory[handle].AddQueueDiscClass(factory);
159 list.push_back(classId);
160 }
161 return list;
162}
163
164uint16_t
165TrafficControlHelper::DoAddChildQueueDisc(uint16_t handle, uint16_t classId, ObjectFactory factory)
166{
167 NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
168 "A queue disc with handle " << handle << " does not exist");
169
170 auto childHandle = static_cast<uint16_t>(m_queueDiscFactory.size());
171 m_queueDiscFactory.emplace_back(factory);
172 m_queueDiscFactory[handle].SetChildQueueDisc(classId, childHandle);
173
174 return childHandle;
175}
176
180 ObjectFactory factory)
181{
183 for (auto c = classes.begin(); c != classes.end(); c++)
184 {
185 uint16_t childHandle = DoAddChildQueueDisc(handle, *c, factory);
186 list.push_back(childHandle);
187 }
188 return list;
189}
190
193{
194 QueueDiscContainer container;
195
196 // A TrafficControlLayer object is aggregated by the InternetStackHelper, but check
197 // anyway because a queue disc has no effect without a TrafficControlLayer object
198 Ptr<TrafficControlLayer> tc = d->GetNode()->GetObject<TrafficControlLayer>();
199 NS_ASSERT(tc);
200
201 // Start from an empty vector of queue discs
202 m_queueDiscs.clear();
203 m_queueDiscs.resize(m_queueDiscFactory.size());
204
205 // Create queue discs (from leaves to root)
206 for (auto i = m_queueDiscFactory.size(); i-- > 0;)
207 {
208 m_queueDiscs[i] = m_queueDiscFactory[i].CreateQueueDisc(m_queueDiscs);
209 }
210
211 // Set the root queue disc (if any has been created) on the device
212 if (!m_queueDiscs.empty() && m_queueDiscs[0])
213 {
214 tc->SetRootQueueDiscOnDevice(d, m_queueDiscs[0]);
215 container.Add(m_queueDiscs[0]);
216 }
217
218 // Queue limits objects can only be installed if a netdevice queue interface
219 // has been aggregated to the netdevice. This is normally the case if the
220 // netdevice has been created via helpers. Abort the simulation if not.
221 if (m_queueLimitsFactory.GetTypeId().GetUid())
222 {
224 NS_ABORT_MSG_IF(!ndqi,
225 "A NetDeviceQueueInterface object has not been"
226 "aggregated to the NetDevice");
227 for (std::size_t i = 0; i < ndqi->GetNTxQueues(); i++)
228 {
230 ndqi->GetTxQueue(i)->SetQueueLimits(ql);
231 }
232 }
233
234 return container;
235}
236
239{
240 QueueDiscContainer container;
241
242 for (auto i = c.Begin(); i != c.End(); ++i)
243 {
244 container.Add(Install(*i));
245 }
246
247 return container;
248}
249
250void
252{
253 Ptr<TrafficControlLayer> tc = d->GetNode()->GetObject<TrafficControlLayer>();
254 NS_ASSERT(tc);
255
256 tc->DeleteRootQueueDiscOnDevice(d);
257 // remove the queue limits objects installed on the device transmission queues
259 // if a queue disc has been installed on the device, a netdevice queue interface
260 // must have been aggregated to the device
261 NS_ASSERT(ndqi);
262 for (std::size_t i = 0; i < ndqi->GetNTxQueues(); i++)
263 {
264 ndqi->GetTxQueue(i)->SetQueueLimits(nullptr);
265 }
266}
267
268void
270{
271 for (auto i = c.Begin(); i != c.End(); ++i)
272 {
273 Uninstall(*i);
274 }
275}
276
277} // namespace ns3
holds a vector of ns3::NetDevice pointers
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
Network device transmission queue interface.
Instantiate subclasses of ns3::Object.
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
Holds a vector of ns3::QueueDisc pointers.
std::vector< ObjectFactory > m_internalQueuesFactory
Vector of factories to create internal queues.
uint16_t AddQueueDiscClass(ObjectFactory factory)
Add a factory to create a queue disc class.
void AddInternalQueue(ObjectFactory factory)
Add a factory to create an internal queue.
void AddPacketFilter(ObjectFactory factory)
Add a factory to create a packet filter.
Ptr< QueueDisc > CreateQueueDisc(const std::vector< Ptr< QueueDisc > > &queueDiscs)
Create a queue disc with the currently stored configuration.
void SetChildQueueDisc(uint16_t classId, uint16_t handle)
Set the (child) queue disc to attach to a class.
std::map< uint16_t, uint16_t > m_classIdChildHandleMap
Map storing the associations between class IDs and child queue disc handles.
std::vector< ObjectFactory > m_packetFiltersFactory
Vector of factories to create packet filters.
ObjectFactory m_queueDiscFactory
Factory to create this queue disc.
std::vector< ObjectFactory > m_queueDiscClassesFactory
Vector of factories to create queue disc classes.
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition queue-disc.h:173
Queue< QueueDiscItem > InternalQueue
Internal queues store QueueDiscItem objects.
Definition queue-disc.h:417
Abstract base class for NetDevice queue length controller.
Build a set of QueueDisc objects.
std::vector< uint16_t > HandleList
Container type for Handlers.
QueueDiscContainer Install(NetDeviceContainer c)
std::vector< Ptr< QueueDisc > > m_queueDiscs
Vector of all the created queue discs.
uint16_t DoSetRootQueueDisc(ObjectFactory factory)
Actual implementation of the SetRootQueueDisc method.
uint16_t DoAddChildQueueDisc(uint16_t handle, uint16_t classId, ObjectFactory factory)
Actual implementation of the AddChildQueueDisc method.
TrafficControlHelper()
Create a TrafficControlHelper to make life easier when creating QueueDisc objects.
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void DoAddInternalQueues(uint16_t handle, uint16_t count, ObjectFactory factory)
Actual implementation of the AddInternalQueues method.
void DoAddPacketFilter(uint16_t handle, ObjectFactory factory)
Actual implementation of the AddPacketFilter method.
ObjectFactory m_queueLimitsFactory
Factory to create a queue limits object.
void Uninstall(NetDeviceContainer c)
ClassIdList DoAddQueueDiscClasses(uint16_t handle, uint16_t count, ObjectFactory factory)
Actual implementation of the AddQueueDiscClasses method.
std::vector< uint16_t > ClassIdList
Container type for Class IDs.
static TrafficControlHelper Default(std::size_t nTxQueues=1)
ClassIdList AddQueueDiscClasses(uint16_t handle, uint16_t count, const std::string &type, Args &&... args)
Helper function used to add the given number of queue disc classes (of the given type and with the gi...
std::vector< QueueDiscFactory > m_queueDiscFactory
QueueDisc factory, stores the configuration of all the queue discs.
HandleList DoAddChildQueueDiscs(uint16_t handle, const ClassIdList &classes, ObjectFactory factory)
Actual implementation of the AddChildQueueDiscs method.
HandleList AddChildQueueDiscs(uint16_t handle, const ClassIdList &classes, const std::string &type, Args &&... args)
Helper function used to attach a child queue disc (of the given type and with the given attributes) t...
The Traffic Control layer aims at introducing an equivalent of the Linux Traffic Control infrastructu...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.
#define list