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
209  Ptr<TrafficControlLayer> tc = d->GetNode ()->GetObject<TrafficControlLayer> ();
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 {
263  Ptr<TrafficControlLayer> tc = d->GetNode ()->GetObject<TrafficControlLayer> ();
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
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
QueueDiscContainer Install(NetDeviceContainer c)
QueueDiscFactory()
Default constructor.
void AddQueueDiscClass(Ptr< QueueDiscClass > qdClass)
Add a queue disc class to the tail of the list of classes.
Definition: queue-disc.cc:634
ClassIdList DoAddQueueDiscClasses(uint16_t handle, uint16_t count, ObjectFactory factory)
Actual implementation of the AddQueueDiscClasses method.
Iterator End(void) const
Get an iterator which indicates past-the-last NetDevice in the container.
Introspection did not find any typical Config paths.
std::vector< ObjectFactory > m_queueDiscClassesFactory
Vector of factories to create queue disc classes.
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
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...
QueueDisc is an abstract base class providing the interface and implementing the operations common to...
Definition: queue-disc.h:181
std::vector< Ptr< QueueDisc > > m_queueDiscs
Vector of all the created queue discs.
void Uninstall(NetDeviceContainer c)
Abstract base class for NetDevice queue length controller.
Definition: queue-limits.h:43
void SetChildQueueDisc(uint16_t classId, uint16_t handle)
Set the (child) queue disc to attach to a class.
Holds a vector of ns3::QueueDisc pointers.
ObjectFactory m_queueDiscFactory
Factory to create this queue disc.
void AddInternalQueue(Ptr< InternalQueue > queue)
Add an internal queue to the tail of the list of queues.
Definition: queue-disc.cc:581
TrafficControlHelper()
Create a TrafficControlHelper to make life easier when creating QueueDisc objects.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Iterator Begin(void) const
Get an iterator which refers to the first NetDevice in the container.
holds a vector of ns3::NetDevice pointers
Build a set of QueueDisc objects.
Ptr< QueueDisc > CreateQueueDisc(const std::vector< Ptr< QueueDisc > > &queueDiscs)
Create a queue disc with the currently stored configuration.
Network device transmission queue interface.
#define list
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...
std::vector< uint16_t > ClassIdList
Container type for Class IDs.
uint16_t AddQueueDiscClass(ObjectFactory factory)
Add a factory to create a queue disc class.
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1185
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
static TrafficControlHelper Default(std::size_t nTxQueues=1)
std::vector< ObjectFactory > m_internalQueuesFactory
Vector of factories to create internal queues.
void AddInternalQueue(ObjectFactory factory)
Add a factory to create an internal queue.
ObjectFactory m_queueLimitsFactory
Factory to create a queue limits object.
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...
void AddPacketFilter(ObjectFactory factory)
Add a factory to create a packet filter.
TypeId GetTypeId(void) const
Get the TypeId which will be created by this ObjectFactory.
Instantiate subclasses of ns3::Object.
std::vector< ObjectFactory > m_packetFiltersFactory
Vector of factories to create packet filters.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
std::vector< QueueDiscFactory > m_queueDiscFactory
QueueDisc factory, stores the configuration of all the queue discs.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
Introspection did not find any typical Config paths.
std::map< uint16_t, uint16_t > m_classIdChildHandleMap
Map storing the associations between class IDs and child queue disc handles.
std::vector< Ptr< NetDevice > >::const_iterator Iterator
NetDevice container iterator.
uint16_t DoSetRootQueueDisc(ObjectFactory factory)
Actual implementation of the SetRootQueueDisc method.
PacketFilter is the abstract base class for filters used by queue discs to classify packets...
Definition: packet-filter.h:34
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:614
This class stores object factories required to create a queue disc and all of its components (packet ...
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.
uint16_t DoAddChildQueueDisc(uint16_t handle, uint16_t classId, ObjectFactory factory)
Actual implementation of the AddChildQueueDisc method.
HandleList DoAddChildQueueDiscs(uint16_t handle, const ClassIdList &classes, ObjectFactory factory)
Actual implementation of the AddChildQueueDiscs method.
void Add(QueueDiscContainer other)
Append the contents of another QueueDiscContainer to the end of this container.
std::vector< uint16_t > HandleList
Container type for Handlers.