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
25 : m_queueDiscFactory(factory)
26{
27}
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.
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.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
TypeId GetTypeId() const
Get the TypeId which will be created by this ObjectFactory.
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
Introspection did not find any typical Config paths.
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
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...
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition type-id.cc:1275
#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