A Discrete-Event Network Simulator
API
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  * 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 <stavallo@unina.it>
18  */
19 
20 #include "traffic-control-helper.h"
21 
22 #include "ns3/abort.h"
23 #include "ns3/log.h"
24 #include "ns3/net-device-queue-interface.h"
25 #include "ns3/pointer.h"
26 #include "ns3/queue-limits.h"
27 #include "ns3/traffic-control-layer.h"
28 #include "ns3/uinteger.h"
29 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE("TrafficControlHelper");
34 
36  : m_queueDiscFactory(factory)
37 {
38 }
39 
40 void
42 {
43  m_internalQueuesFactory.push_back(factory);
44 }
45 
46 void
48 {
49  m_packetFiltersFactory.push_back(factory);
50 }
51 
52 uint16_t
54 {
55  m_queueDiscClassesFactory.push_back(factory);
56  return static_cast<uint16_t>(m_queueDiscClassesFactory.size() - 1);
57 }
58 
59 void
60 QueueDiscFactory::SetChildQueueDisc(uint16_t classId, uint16_t handle)
61 {
63  "Cannot attach a queue disc to a non existing class");
64  m_classIdChildHandleMap[classId] = handle;
65 }
66 
68 QueueDiscFactory::CreateQueueDisc(const std::vector<Ptr<QueueDisc>>& queueDiscs)
69 {
70  // create the queue disc
72 
73  // create and add the internal queues
74  for (std::vector<ObjectFactory>::iterator i = m_internalQueuesFactory.begin();
75  i != m_internalQueuesFactory.end();
76  i++)
77  {
79  }
80 
81  // create and add the packet filters
82  for (std::vector<ObjectFactory>::iterator i = m_packetFiltersFactory.begin();
83  i != m_packetFiltersFactory.end();
84  i++)
85  {
86  qd->AddPacketFilter(i->Create<PacketFilter>());
87  }
88 
89  // create and add the queue disc classes
90  for (std::size_t i = 0; i < m_queueDiscClassesFactory.size(); i++)
91  {
92  // the class ID is given by the index i of the vector
94  "Cannot create a queue disc class with no attached queue disc");
95 
96  uint16_t handle = m_classIdChildHandleMap[i];
97  NS_ABORT_MSG_IF(handle >= queueDiscs.size() || !queueDiscs[handle],
98  "A queue disc with handle " << handle << " has not been created yet");
99 
100  m_queueDiscClassesFactory[i].Set("QueueDisc", PointerValue(queueDiscs[handle]));
101  qd->AddQueueDiscClass(m_queueDiscClassesFactory[i].Create<QueueDiscClass>());
102  }
103 
104  return qd;
105 }
106 
108 {
109 }
110 
112 TrafficControlHelper::Default(std::size_t nTxQueues)
113 {
114  NS_LOG_FUNCTION(nTxQueues);
115  NS_ABORT_MSG_IF(nTxQueues == 0, "The device must have at least one queue");
116  TrafficControlHelper helper;
117 
118  if (nTxQueues == 1)
119  {
120  helper.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
121  }
122  else
123  {
124  uint16_t handle = helper.SetRootQueueDisc("ns3::MqQueueDisc");
125  ClassIdList cls = helper.AddQueueDiscClasses(handle, nTxQueues, "ns3::QueueDiscClass");
126  helper.AddChildQueueDiscs(handle, cls, "ns3::FqCoDelQueueDisc");
127  }
128  return helper;
129 }
130 
131 uint16_t
133 {
135  "A root queue disc has been already added to this factory");
136 
137  m_queueDiscFactory.emplace_back(factory);
138  return 0;
139 }
140 
141 void
142 TrafficControlHelper::DoAddInternalQueues(uint16_t handle, uint16_t count, ObjectFactory factory)
143 {
144  NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
145  "A queue disc with handle " << handle << " does not exist");
146 
147  for (int i = 0; i < count; i++)
148  {
149  m_queueDiscFactory[handle].AddInternalQueue(factory);
150  }
151 }
152 
153 void
155 {
156  NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
157  "A queue disc with handle " << handle << " does not exist");
158 
159  m_queueDiscFactory[handle].AddPacketFilter(factory);
160 }
161 
163 TrafficControlHelper::DoAddQueueDiscClasses(uint16_t handle, uint16_t count, ObjectFactory factory)
164 {
165  NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
166  "A queue disc with handle " << handle << " does not exist");
167 
169  uint16_t classId;
170 
171  for (int i = 0; i < count; i++)
172  {
173  classId = m_queueDiscFactory[handle].AddQueueDiscClass(factory);
174  list.push_back(classId);
175  }
176  return list;
177 }
178 
179 uint16_t
180 TrafficControlHelper::DoAddChildQueueDisc(uint16_t handle, uint16_t classId, ObjectFactory factory)
181 {
182  NS_ABORT_MSG_IF(handle >= m_queueDiscFactory.size(),
183  "A queue disc with handle " << handle << " does not exist");
184 
185  uint16_t childHandle = static_cast<uint16_t>(m_queueDiscFactory.size());
186  m_queueDiscFactory.emplace_back(factory);
187  m_queueDiscFactory[handle].SetChildQueueDisc(classId, childHandle);
188 
189  return childHandle;
190 }
191 
194  const TrafficControlHelper::ClassIdList& classes,
195  ObjectFactory factory)
196 {
198  for (ClassIdList::const_iterator c = classes.begin(); c != classes.end(); c++)
199  {
200  uint16_t childHandle = DoAddChildQueueDisc(handle, *c, factory);
201  list.push_back(childHandle);
202  }
203  return list;
204 }
205 
208 {
209  QueueDiscContainer container;
210 
211  // A TrafficControlLayer object is aggregated by the InternetStackHelper, but check
212  // anyway because a queue disc has no effect without a TrafficControlLayer object
213  Ptr<TrafficControlLayer> tc = d->GetNode()->GetObject<TrafficControlLayer>();
214  NS_ASSERT(tc);
215 
216  // Start from an empty vector of queue discs
217  m_queueDiscs.clear();
218  m_queueDiscs.resize(m_queueDiscFactory.size());
219 
220  // Create queue discs (from leaves to root)
221  for (auto i = m_queueDiscFactory.size(); i-- > 0;)
222  {
223  m_queueDiscs[i] = m_queueDiscFactory[i].CreateQueueDisc(m_queueDiscs);
224  }
225 
226  // Set the root queue disc (if any has been created) on the device
227  if (!m_queueDiscs.empty() && m_queueDiscs[0])
228  {
229  tc->SetRootQueueDiscOnDevice(d, m_queueDiscs[0]);
230  container.Add(m_queueDiscs[0]);
231  }
232 
233  // Queue limits objects can only be installed if a netdevice queue interface
234  // has been aggregated to the netdevice. This is normally the case if the
235  // netdevice has been created via helpers. Abort the simulation if not.
237  {
239  NS_ABORT_MSG_IF(!ndqi,
240  "A NetDeviceQueueInterface object has not been"
241  "aggregated to the NetDevice");
242  for (std::size_t i = 0; i < ndqi->GetNTxQueues(); i++)
243  {
245  ndqi->GetTxQueue(i)->SetQueueLimits(ql);
246  }
247  }
248 
249  return container;
250 }
251 
254 {
255  QueueDiscContainer container;
256 
257  for (NetDeviceContainer::Iterator i = c.Begin(); i != c.End(); ++i)
258  {
259  container.Add(Install(*i));
260  }
261 
262  return container;
263 }
264 
265 void
267 {
268  Ptr<TrafficControlLayer> tc = d->GetNode()->GetObject<TrafficControlLayer>();
269  NS_ASSERT(tc);
270 
271  tc->DeleteRootQueueDiscOnDevice(d);
272  // remove the queue limits objects installed on the device transmission queues
274  // if a queue disc has been installed on the device, a netdevice queue interface
275  // must have been aggregated to the device
276  NS_ASSERT(ndqi);
277  for (std::size_t i = 0; i < ndqi->GetNTxQueues(); i++)
278  {
279  ndqi->GetTxQueue(i)->SetQueueLimits(nullptr);
280  }
281 }
282 
283 void
285 {
286  for (NetDeviceContainer::Iterator i = c.Begin(); i != c.End(); ++i)
287  {
288  Uninstall(*i);
289  }
290 }
291 
292 } // namespace ns3
holds a vector of ns3::NetDevice pointers
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
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.
Definition: packet-filter.h:35
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Introspection did not find any typical Config paths.
Holds a vector of ns3::QueueDisc pointers.
void Add(QueueDiscContainer other)
Append the contents of another QueueDiscContainer to the end of this container.
Ptr< QueueDisc > CreateQueueDisc(const std::vector< Ptr< QueueDisc >> &queueDiscs)
Create a queue disc with the currently stored configuration.
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.
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:184
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:577
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:628
void AddPacketFilter(Ptr< PacketFilter > filter)
Add a packet filter to the tail of the list of filters used to classify packets.
Definition: queue-disc.cc:608
Abstract base class for NetDevice queue length controller.
Definition: queue-limits.h:44
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:1209
#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_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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.
#define list