A Discrete-Event Network Simulator
API
traffic-control-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/abort.h"
23 #include "ns3/queue-limits.h"
24 #include "ns3/net-device-queue-interface.h"
25 #include "ns3/uinteger.h"
26 #include "ns3/pointer.h"
27 #include "ns3/traffic-control-layer.h"
28 #include "traffic-control-helper.h"
29 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("TrafficControlHelper");
33 
35  : m_queueDiscFactory (factory)
36 {
37 }
38 
39 void
41 {
42  m_internalQueuesFactory.push_back (factory);
43 }
44 
45 void
47 {
48  m_packetFiltersFactory.push_back (factory);
49 }
50 
51 uint16_t
53 {
54  m_queueDiscClassesFactory.push_back (factory);
55  return static_cast<uint16_t>(m_queueDiscClassesFactory.size () - 1);
56 }
57 
58 void
59 QueueDiscFactory::SetChildQueueDisc (uint16_t classId, uint16_t handle)
60 {
61  NS_ABORT_MSG_IF (classId >= m_queueDiscClassesFactory.size (),
62  "Cannot attach a queue disc to a non existing class");
63  m_classIdChildHandleMap[classId] = handle;
64 }
65 
67 QueueDiscFactory::CreateQueueDisc (const std::vector<Ptr<QueueDisc> > & queueDiscs)
68 {
69  // create the queue disc
71 
72  // create and add the internal queues
73  for (std::vector<ObjectFactory>::iterator i = m_internalQueuesFactory.begin ();
74  i != m_internalQueuesFactory.end (); i++ )
75  {
76  qd->AddInternalQueue (i->Create<QueueDisc::InternalQueue> ());
77  }
78 
79  // create and add the packet filters
80  for (std::vector<ObjectFactory>::iterator i = m_packetFiltersFactory.begin ();
81  i != m_packetFiltersFactory.end (); i++ )
82  {
83  qd->AddPacketFilter (i->Create<PacketFilter> ());
84  }
85 
86  // create and add the queue disc classes
87  for (uint16_t i = 0; i < m_queueDiscClassesFactory.size (); i++)
88  {
89  // the class ID is given by the index i of the vector
91  "Cannot create a queue disc class with no attached queue disc");
92 
93  uint16_t handle = m_classIdChildHandleMap[i];
94  NS_ABORT_MSG_IF (handle >= queueDiscs.size () || queueDiscs[handle] == 0,
95  "A queue disc with handle " << handle << " has not been created yet");
96 
97  m_queueDiscClassesFactory[i].Set ("QueueDisc", PointerValue (queueDiscs[handle]));
98  qd->AddQueueDiscClass (m_queueDiscClassesFactory[i].Create<QueueDiscClass> ());
99  }
100 
101  return qd;
102 }
103 
104 
106 {
107 }
108 
110 TrafficControlHelper::Default (std::size_t nTxQueues)
111 {
112  NS_LOG_FUNCTION (nTxQueues);
113  NS_ABORT_MSG_IF (nTxQueues == 0, "The device must have at least one queue");
114  TrafficControlHelper helper;
115 
116  if (nTxQueues == 1)
117  {
118  helper.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
119  }
120  else
121  {
122  uint16_t handle = helper.SetRootQueueDisc ("ns3::MqQueueDisc");
123  ClassIdList cls = helper.AddQueueDiscClasses (handle, nTxQueues, "ns3::QueueDiscClass");
124  helper.AddChildQueueDiscs (handle, cls, "ns3::FqCoDelQueueDisc");
125  }
126  return helper;
127 }
128 
129 uint16_t
131 {
132  NS_ABORT_MSG_UNLESS (m_queueDiscFactory.empty (), "A root queue disc has been already added to this factory");
133 
134  m_queueDiscFactory.push_back (QueueDiscFactory (factory));
135  return 0;
136 }
137 
138 void
139 TrafficControlHelper::DoAddInternalQueues (uint16_t handle, uint16_t count, ObjectFactory factory)
140 {
141  NS_ABORT_MSG_IF (handle >= m_queueDiscFactory.size (), "A queue disc with handle "
142  << handle << " does not exist");
143 
144  for (int i = 0; i < count; i++)
145  {
146  m_queueDiscFactory[handle].AddInternalQueue (factory);
147  }
148 }
149 
150 void
152 {
153  NS_ABORT_MSG_IF (handle >= m_queueDiscFactory.size (), "A queue disc with handle "
154  << handle << " does not exist");
155 
156  m_queueDiscFactory[handle].AddPacketFilter (factory);
157 }
158 
160 TrafficControlHelper::DoAddQueueDiscClasses (uint16_t handle, uint16_t count, ObjectFactory factory)
161 {
162  NS_ABORT_MSG_IF (handle >= m_queueDiscFactory.size (), "A queue disc with handle "
163  << handle << " does not exist");
164 
166  uint16_t classId;
167 
168  for (int i = 0; i < count; i++)
169  {
170  classId = m_queueDiscFactory[handle].AddQueueDiscClass (factory);
171  list.push_back (classId);
172  }
173  return list;
174 }
175 
176 uint16_t
177 TrafficControlHelper::DoAddChildQueueDisc (uint16_t handle, uint16_t classId, ObjectFactory factory)
178 {
179  NS_ABORT_MSG_IF (handle >= m_queueDiscFactory.size (), "A queue disc with handle "
180  << handle << " does not exist");
181 
182  uint16_t childHandle = static_cast<uint16_t>(m_queueDiscFactory.size ());
183  m_queueDiscFactory.push_back (QueueDiscFactory (factory));
184  m_queueDiscFactory[handle].SetChildQueueDisc (classId, childHandle);
185 
186  return childHandle;
187 }
188 
191  ObjectFactory factory)
192 {
194  for (ClassIdList::const_iterator c = classes.begin (); c != classes.end (); c++)
195  {
196  uint16_t childHandle = DoAddChildQueueDisc (handle, *c, factory);
197  list.push_back (childHandle);
198  }
199  return list;
200 }
201 
204 {
205  QueueDiscContainer container;
206 
207  // A TrafficControlLayer object is aggregated by the InternetStackHelper, but check
208  // anyway because a queue disc has no effect without a TrafficControlLayer object
210  NS_ASSERT (tc != 0);
211 
212  // Start from an empty vector of queue discs
213  m_queueDiscs.clear ();
214  m_queueDiscs.resize (m_queueDiscFactory.size ());
215 
216  // Create queue discs (from leaves to root)
217  for (auto i = m_queueDiscFactory.size (); i-- > 0; )
218  {
219  m_queueDiscs[i] = m_queueDiscFactory[i].CreateQueueDisc (m_queueDiscs);
220  }
221 
222  // Set the root queue disc (if any has been created) on the device
223  if (!m_queueDiscs.empty () && m_queueDiscs[0])
224  {
225  tc->SetRootQueueDiscOnDevice (d, m_queueDiscs[0]);
226  container.Add (m_queueDiscs[0]);
227  }
228 
229  // Queue limits objects can only be installed if a netdevice queue interface
230  // has been aggregated to the netdevice. This is normally the case if the
231  // netdevice has been created via helpers. Abort the simulation if not.
233  {
235  NS_ABORT_MSG_IF (!ndqi, "A NetDeviceQueueInterface object has not been"
236  "aggregated to the NetDevice");
237  for (uint8_t i = 0; i < ndqi->GetNTxQueues (); i++)
238  {
240  ndqi->GetTxQueue (i)->SetQueueLimits (ql);
241  }
242  }
243 
244  return container;
245 }
246 
249 {
250  QueueDiscContainer container;
251 
252  for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
253  {
254  container.Add (Install (*i));
255  }
256 
257  return container;
258 }
259 
260 void
262 {
264  NS_ASSERT (tc != 0);
265 
266  tc->DeleteRootQueueDiscOnDevice (d);
267  // remove the queue limits objects installed on the device transmission queues
269  // if a queue disc has been installed on the device, a netdevice queue interface
270  // must have been aggregated to the device
271  NS_ASSERT (ndqi);
272  for (uint8_t i = 0; i < ndqi->GetNTxQueues (); i++)
273  {
274  ndqi->GetTxQueue (i)->SetQueueLimits (0);
275  }
276 }
277 
278 void
280 {
281  for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
282  {
283  Uninstall (*i);
284  }
285 }
286 
287 
288 } // namespace ns3
holds a vector of ns3::NetDevice pointers
Iterator End(void) const
Get an iterator which indicates past-the-last NetDevice in the container.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
Iterator Begin(void) const
Get an iterator which refers to the first NetDevice in the container.
virtual Ptr< Node > GetNode(void) const =0
Network device transmission queue interface.
Instantiate subclasses of ns3::Object.
TypeId GetTypeId(void) const
Get the TypeId which will be created by this ObjectFactory.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
PacketFilter is the abstract base class for filters used by queue discs to classify packets.
Definition: packet-filter.h:34
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.
This class stores object factories required to create a queue disc and all of its components (packet ...
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:181
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:579
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:632
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:612
Abstract base class for NetDevice queue length controller.
Definition: queue-limits.h:43
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...
Introspection did not find any typical Config paths.
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1184
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:205
#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