A Discrete-Event Network Simulator
API
traffic-control-layer.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
4  * 2016 Stefano Avallone <stavallo@unina.it>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #include "traffic-control-layer.h"
21 #include "ns3/log.h"
22 #include "ns3/object-vector.h"
23 #include "ns3/packet.h"
24 #include "ns3/queue-disc.h"
25 
26 namespace ns3 {
27 
28 NS_LOG_COMPONENT_DEFINE ("TrafficControlLayer");
29 
30 NS_OBJECT_ENSURE_REGISTERED (TrafficControlLayer);
31 
32 TypeId
34 {
35  static TypeId tid = TypeId ("ns3::TrafficControlLayer")
36  .SetParent<Object> ()
37  .SetGroupName ("TrafficControl")
38  .AddConstructor<TrafficControlLayer> ()
39  .AddAttribute ("RootQueueDiscList", "The list of root queue discs associated to this Traffic Control layer.",
42  MakeObjectVectorChecker<QueueDisc> ())
43  ;
44  return tid;
45 }
46 
47 TypeId
49 {
50  return GetTypeId ();
51 }
52 
54  : Object ()
55 {
57 }
58 
59 void
61 {
62  NS_LOG_FUNCTION (this);
63  m_node = 0;
64  m_rootQueueDiscs.clear ();
65  m_handlers.clear ();
68 }
69 
70 void
72 {
73  NS_LOG_FUNCTION (this);
74  for (uint32_t j = 0; j < m_rootQueueDiscs.size (); j++)
75  {
76  if (m_rootQueueDiscs[j])
77  {
78  Ptr<NetDevice> device = m_node->GetDevice (j);
79  // NetDevices supporting flow control can set the number of device transmission
80  // queues through the NetDevice queue interface during initialization. Thus,
81  // ensure that the device has completed initialization
82  device->Initialize ();
83 
84  std::map<Ptr<NetDevice>, NetDeviceInfo>::iterator qdMap = m_netDeviceQueueToQueueDiscMap.find (device);
85  NS_ASSERT (qdMap != m_netDeviceQueueToQueueDiscMap.end ());
86  Ptr<NetDeviceQueueInterface> devQueueIface = qdMap->second.first;
87  NS_ASSERT (devQueueIface);
88 
89  devQueueIface->SetQueueDiscInstalled (true);
90 
91  // set the wake callbacks on netdevice queues
92  if (m_rootQueueDiscs[j]->GetWakeMode () == QueueDisc::WAKE_ROOT)
93  {
94  for (uint32_t i = 0; i < devQueueIface->GetTxQueuesN (); i++)
95  {
96  devQueueIface->GetTxQueue (i)->SetWakeCallback (MakeCallback (&QueueDisc::Run, m_rootQueueDiscs[j]));
97  qdMap->second.second.push_back (m_rootQueueDiscs[j]);
98  }
99  }
100  else if (m_rootQueueDiscs[j]->GetWakeMode () == QueueDisc::WAKE_CHILD)
101  {
102  NS_ASSERT_MSG (m_rootQueueDiscs[j]->GetNQueueDiscClasses () == devQueueIface->GetTxQueuesN (),
103  "The number of child queue discs does not match the number of netdevice queues");
104  for (uint32_t i = 0; i < devQueueIface->GetTxQueuesN (); i++)
105  {
106  devQueueIface->GetTxQueue (i)->SetWakeCallback (MakeCallback (&QueueDisc::Run,
107  m_rootQueueDiscs[j]->GetQueueDiscClass (i)->GetQueueDisc ()));
108  qdMap->second.second.push_back (m_rootQueueDiscs[j]->GetQueueDiscClass (i)->GetQueueDisc ());
109  }
110  }
111 
112  // initialize the queue disc
113  m_rootQueueDiscs[j]->Initialize ();
114  }
115  }
117 }
118 
119 void
121 {
122  NS_LOG_FUNCTION (this << device);
123 
124  // ensure this setup is done just once (in case of dual stack nodes)
125  if (device->GetObject<NetDeviceQueueInterface> ())
126  {
127  NS_LOG_DEBUG ("The setup for this device has been already done.");
128  return;
129  }
130 
131  // create a NetDeviceQueueInterface object and aggregate it to the device
132  Ptr<NetDeviceQueueInterface> devQueueIface = CreateObject<NetDeviceQueueInterface> ();
133  device->AggregateObject (devQueueIface);
134 
135  // store a pointer to the created queue interface
137  "This is a bug: SetupDevice should be called only once per device");
138 
139  m_netDeviceQueueToQueueDiscMap[device] = NetDeviceInfo (devQueueIface, QueueDiscVector ());
140 }
141 
142 void
144  uint16_t protocolType, Ptr<NetDevice> device)
145 {
146  NS_LOG_FUNCTION (this << protocolType << device);
147 
148  struct ProtocolHandlerEntry entry;
149  entry.handler = handler;
150  entry.protocol = protocolType;
151  entry.device = device;
152  entry.promiscuous = false;
153 
154  m_handlers.push_back (entry);
155 
156  NS_LOG_DEBUG ("Handler for NetDevice: " << device << " registered for protocol " <<
157  protocolType << ".");
158 }
159 
160 void
162 {
163  NS_LOG_FUNCTION (this << device);
164 
165  uint32_t index = GetDeviceIndex (device);
166  NS_ASSERT_MSG (index < m_node->GetNDevices (), "The provided device does not belong to"
167  << " the node which this TrafficControlLayer object is aggregated to" );
168  if (index >= m_rootQueueDiscs.size ())
169  {
170  m_rootQueueDiscs.resize (index+1);
171  }
172 
173  NS_ASSERT_MSG (m_rootQueueDiscs[index] == 0, "Cannot install a root queue disc on a "
174  << "device already having one. Delete the existing queue disc first.");
175 
176  m_rootQueueDiscs[index] = qDisc;
177 }
178 
181 {
182  NS_LOG_FUNCTION (this << device);
183 
184  uint32_t index = GetDeviceIndex (device);
185  NS_ASSERT_MSG (index < m_node->GetNDevices (), "The provided device does not belong to"
186  << " the node which this TrafficControlLayer object is aggregated to" );
187  if (index >= m_rootQueueDiscs.size ())
188  {
189  m_rootQueueDiscs.resize (index+1);
190  }
191  return m_rootQueueDiscs[index];
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this << device);
198 
199  uint32_t index = GetDeviceIndex (device);
200  NS_ASSERT_MSG (index < m_node->GetNDevices (), "The provided device does not belong to"
201  << " the node which this TrafficControlLayer object is aggregated to" );
202 
203  NS_ASSERT_MSG (index < m_rootQueueDiscs.size () && m_rootQueueDiscs[index] != 0, "No root queue disc"
204  << " installed on device " << device);
205 
206  // remove the root queue disc
207  m_rootQueueDiscs[index] = 0;
208 }
209 
210 void
212 {
213  NS_LOG_FUNCTION (this << node);
214  m_node = node;
215 }
216 
217 void
219 {
220  NS_LOG_FUNCTION (this);
221  if (m_node == 0)
222  {
223  Ptr<Node> node = this->GetObject<Node> ();
224  //verify that it's a valid node and that
225  //the node was not set before
226  if (node != 0)
227  {
228  this->SetNode (node);
229  }
230  }
232 }
233 
234 uint32_t
236 {
237  NS_LOG_FUNCTION (this << device);
238  uint32_t i;
239  for (i = 0; i < m_node->GetNDevices () && device != m_node->GetDevice (i); i++);
240  return i;
241 }
242 
243 void
245  uint16_t protocol, const Address &from, const Address &to,
246  NetDevice::PacketType packetType)
247 {
248  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
249 
250  bool found = false;
251 
252  for (ProtocolHandlerList::iterator i = m_handlers.begin ();
253  i != m_handlers.end (); i++)
254  {
255  if (i->device == 0
256  || (i->device != 0 && i->device == device))
257  {
258  if (i->protocol == 0
259  || i->protocol == protocol)
260  {
261  NS_LOG_DEBUG ("Found handler for packet " << p << ", protocol " <<
262  protocol << " and NetDevice " << device <<
263  ". Send packet up");
264  i->handler (device, p, protocol, from, to, packetType);
265  found = true;
266  }
267  }
268  }
269 
270  if (! found)
271  {
272  NS_FATAL_ERROR ("Handler for protocol " << p << " and device " << device <<
273  " not found. It isn't forwarded up; it dies here.");
274  }
275 }
276 
277 void
279 {
280  NS_LOG_FUNCTION (this << device << item);
281 
282  NS_LOG_DEBUG ("Send packet to device " << device << " protocol number " <<
283  item->GetProtocol ());
284 
285  std::map<Ptr<NetDevice>, NetDeviceInfo>::iterator qdMap = m_netDeviceQueueToQueueDiscMap.find (device);
286  NS_ASSERT (qdMap != m_netDeviceQueueToQueueDiscMap.end ());
287  Ptr<NetDeviceQueueInterface> devQueueIface = qdMap->second.first;
288  NS_ASSERT (devQueueIface);
289 
290  // determine the transmission queue of the device where the packet will be enqueued
291  uint8_t txq = devQueueIface->GetSelectedQueue (item);
292  NS_ASSERT (txq < devQueueIface->GetTxQueuesN ());
293 
294  if (qdMap->second.second.empty ())
295  {
296  // The device has no attached queue disc, thus add the header to the packet and
297  // send it directly to the device if the selected queue is not stopped
298  if (!devQueueIface->GetTxQueue (txq)->IsStopped ())
299  {
300  item->AddHeader ();
301  device->Send (item->GetPacket (), item->GetAddress (), item->GetProtocol ());
302  }
303  }
304  else
305  {
306  // Enqueue the packet in the queue disc associated with the netdevice queue
307  // selected for the packet and try to dequeue packets from such queue disc
308  item->SetTxQueueIndex (txq);
309 
310  Ptr<QueueDisc> qDisc = qdMap->second.second[txq];
311  NS_ASSERT (qDisc);
312  qDisc->Enqueue (item);
313  qDisc->Run ();
314  }
315 }
316 
317 } // namespace ns3
virtual void DeleteRootQueueDiscOnDevice(Ptr< NetDevice > device)
This method can be used to remove the root queue disc (and associated filters, classes and queues) in...
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:346
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual void SetRootQueueDiscOnDevice(Ptr< NetDevice > device, Ptr< QueueDisc > qDisc)
This method can be used to set the root queue disc installed on a device.
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
Definition: queue-disc.cc:411
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
Traffic control layer definition.
ProtocolHandlerList m_handlers
List of upper-layer handlers.
bool promiscuous
true if it is a promiscuous handler
virtual void DoInitialize(void)
Initialize() implementation.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
#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
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:538
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:145
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
virtual void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Called by NetDevices, incoming packet.
uint16_t protocol
the protocol number
std::pair< Ptr< NetDeviceQueueInterface >, QueueDiscVector > NetDeviceInfo
Typedef for queue disc vector.
uint32_t GetDeviceIndex(Ptr< NetDevice > device)
Lookup a given Ptr in the node's list of devices.
a polymophic address class
Definition: address.h:90
void SetNode(Ptr< Node > node)
Set node associated with this stack.
void Run(void)
Modelled after the Linux function __qdisc_run (net/sched/sch_generic.c) Dequeues multiple packets...
Definition: queue-disc.cc:454
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:142
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1480
Network device transmission queue interface.
Definition: net-device.h:216
QueueDiscVector m_rootQueueDiscs
This vector stores the root queue discs installed on all the devices of the node. ...
std::vector< Ptr< QueueDisc > > QueueDiscVector
Typedef for queue disc vector.
Ptr< NetDevice > device
the NetDevice
uint32_t GetNDevices(void) const
Definition: node.cc:150
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TypeId GetTypeId(void)
Get the type ID.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
virtual void Send(Ptr< NetDevice > device, Ptr< QueueDiscItem > item)
Called from upper layer to queue a packet for the transmission.
Ptr< Node > m_node
The node this TrafficControlLayer object is aggregated to.
Protocol handler entry.
virtual void SetupDevice(Ptr< NetDevice > device)
Perform the operations that the traffic control layer needs to do when an IPv4/v6 interface is added ...
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
virtual Ptr< QueueDisc > GetRootQueueDiscOnDevice(Ptr< NetDevice > device)
This method can be used to get the root queue disc installed on a device.
Node::ProtocolHandler handler
the protocol handler
std::map< Ptr< NetDevice >, NetDeviceInfo > m_netDeviceQueueToQueueDiscMap
This map plays the role of the qdisc field of the netdev_queue struct in Linux.
A base class which provides memory management and object aggregation.
Definition: object.h:87
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:318
virtual TypeId GetInstanceTypeId(void) const
Get the type ID for the instance.
Container for a set of ns3::Object pointers.
virtual void DoDispose(void)
Destructor implementation.
a unique identifier for an interface.
Definition: type-id.h:58
void RegisterProtocolHandler(Node::ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device)
Register an IN handler.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:826