LEFT | RIGHT |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2005,2006 INRIA | 3 * Copyright (c) 2005,2006 INRIA |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 2 as |
7 * published by the Free Software Foundation; | 7 * published by the Free Software Foundation; |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 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 | 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 | 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 * | 17 * |
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> | 18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
19 * Modified by Emmanuelle Laprise to remove dependence on LLC headers | 19 * Modified by Emmanuelle Laprise to remove dependence on LLC headers |
20 * Modified by Stefano Avallone to add NetDeviceQueue and NetDeviceQueueInterfac
e | |
21 */ | 20 */ |
22 #ifndef NET_DEVICE_H | 21 #ifndef NET_DEVICE_H |
23 #define NET_DEVICE_H | 22 #define NET_DEVICE_H |
24 | 23 |
25 #include <sstream> | |
26 #include <vector> | |
27 #include <stdint.h> | 24 #include <stdint.h> |
28 #include "ns3/callback.h" | 25 #include "ns3/callback.h" |
29 #include "ns3/object.h" | 26 #include "ns3/object.h" |
30 #include "ns3/ptr.h" | 27 #include "ns3/ptr.h" |
31 #include "ns3/log.h" | 28 #include "packet.h" |
32 #include "address.h" | 29 #include "address.h" |
33 #include "ns3/ipv4-address.h" | 30 #include "ns3/ipv4-address.h" |
34 #include "ns3/ipv6-address.h" | 31 #include "ns3/ipv6-address.h" |
35 #include "ns3/queue.h" | |
36 #include "ns3/queue-item.h" | |
37 | 32 |
38 namespace ns3 { | 33 namespace ns3 { |
39 | 34 |
40 class Node; | 35 class Node; |
41 class Channel; | 36 class Channel; |
42 class Packet; | |
43 class QueueLimits; | |
44 class NetDeviceQueueInterface; | |
45 | 37 |
46 /** | 38 /** |
47 * \ingroup network | 39 * \ingroup network |
48 * \defgroup netdevice Network Device | 40 * \defgroup netdevice Network Device |
49 */ | 41 */ |
50 | |
51 /** | |
52 * \ingroup netdevice | |
53 * | |
54 * \brief Network device transmission queue | |
55 * | |
56 * This class stores information about a single transmission queue | |
57 * of a network device that is exposed to queue discs. Such information | |
58 * includes the state of the transmission queue (whether it has been | |
59 * stopped or not) and data used by techniques such as Byte Queue Limits. | |
60 * | |
61 * This class roughly models the struct netdev_queue of Linux. | |
62 */ | |
63 class NetDeviceQueue : public SimpleRefCount<NetDeviceQueue> | |
64 { | |
65 public: | |
66 NetDeviceQueue (); | |
67 virtual ~NetDeviceQueue(); | |
68 | |
69 /** | |
70 * Called by the device to start this device transmission queue. | |
71 * This is the analogous to the netif_tx_start_queue function of the Linux ker
nel. | |
72 */ | |
73 virtual void Start (void); | |
74 | |
75 /** | |
76 * Called by the device to stop this device transmission queue. | |
77 * This is the analogous to the netif_tx_stop_queue function of the Linux kern
el. | |
78 */ | |
79 virtual void Stop (void); | |
80 | |
81 /** | |
82 * Called by the device to wake the queue disc associated with this | |
83 * device transmission queue. This is done by invoking the wake callback. | |
84 * This is the analogous to the netif_tx_wake_queue function of the Linux kern
el. | |
85 */ | |
86 virtual void Wake (void); | |
87 | |
88 /** | |
89 * \brief Get the status of the device transmission queue. | |
90 * \return true if the device transmission queue is stopped. | |
91 * | |
92 * Called by queue discs to enquire about the status of a given transmission q
ueue. | |
93 * This is the analogous to the netif_xmit_stopped function of the Linux kerne
l. | |
94 */ | |
95 bool IsStopped (void) const; | |
96 | |
97 /// Callback invoked by netdevices to wake upper layers | |
98 typedef Callback< void > WakeCallback; | |
99 | |
100 /** | |
101 * \brief Set the wake callback | |
102 * \param cb the callback to set | |
103 * | |
104 * Called by the traffic control layer to set the wake callback. The wake call
back | |
105 * is invoked by the device whenever it is needed to "wake" the upper layers (
i.e., | |
106 * solicitate the queue disc associated with this transmission queue (in case
of | |
107 * multi-queue aware queue discs) or to the network device (otherwise) to send | |
108 * packets down to the device). | |
109 */ | |
110 virtual void SetWakeCallback (WakeCallback cb); | |
111 | |
112 /** | |
113 * \brief Called by the netdevice to report the number of bytes queued to the
device queue | |
114 * \param bytes number of bytes queued to the device queue | |
115 */ | |
116 void NotifyQueuedBytes (uint32_t bytes); | |
117 | |
118 /** | |
119 * \brief Called by the netdevice to report the number of bytes it is going to
transmit | |
120 * \param bytes number of bytes the device is going to transmit | |
121 */ | |
122 void NotifyTransmittedBytes (uint32_t bytes); | |
123 | |
124 /** | |
125 * \brief Reset queue limits state | |
126 */ | |
127 void ResetQueueLimits (); | |
128 | |
129 /** | |
130 * \brief Set queue limits to this queue | |
131 * \param ql the queue limits associated to this queue | |
132 */ | |
133 void SetQueueLimits (Ptr<QueueLimits> ql); | |
134 | |
135 /** | |
136 * \brief Get queue limits to this queue | |
137 * \return the queue limits associated to this queue | |
138 */ | |
139 Ptr<QueueLimits> GetQueueLimits (); | |
140 | |
141 /** | |
142 * \brief Perform the actions required by flow control and dynamic queue | |
143 * limits when a packet is enqueued in the queue of a netdevice | |
144 * | |
145 * \param queue the device queue | |
146 * \param ndqi the NetDeviceQueueInterface object aggregated to the device | |
147 * \param txq the index of the transmission queue associated with the device q
ueue | |
148 * \param item the enqueued packet | |
149 * | |
150 * This method must be connected to the "Enqueue" traced callback of a Queue | |
151 * object (through a bound callback) in order for a netdevice to support | |
152 * flow control and dynamic queue limits. | |
153 */ | |
154 template <typename Item> | |
155 static void PacketEnqueued (Ptr<Queue<Item> > queue, | |
156 Ptr<NetDeviceQueueInterface> ndqi, | |
157 uint8_t txq, Ptr<const Item> item); | |
158 | |
159 /** | |
160 * \brief Perform the actions required by flow control and dynamic queue | |
161 * limits when a packet is dequeued (or dropped after dequeue) from | |
162 * the queue of a netdevice | |
163 * | |
164 * \param queue the device queue | |
165 * \param ndqi the NetDeviceQueueInterface object aggregated to the device | |
166 * \param txq the index of the transmission queue associated with the device q
ueue | |
167 * \param item the dequeued (or dropped after dequeue) packet | |
168 * | |
169 * This method must be connected to the "Dequeue" and "DropAfterDequeue" | |
170 * traced callbacks of a Queue object (through a bound callback) in order for | |
171 * a netdevice to support flow control and dynamic queue limits. | |
172 * | |
173 * Note that this method is invoked before the dequeued packet is actually | |
174 * returned to the device and calls the wake callback when there is room for | |
175 * another packet. If the queue is stopped, the wake callback invokes the | |
176 * queue disc Run method, which sends another packet to the netdevice. This | |
177 * event might trigger the dequeue of another packet, which would be processed | |
178 * before the previous one is returned to the netdevice. In order to avoid | |
179 * that, the netdevice must set the InOrderDequeue attribute of its queues | |
180 * to true. | |
181 */ | |
182 template <typename Item> | |
183 static void PacketDequeued (Ptr<Queue<Item> > queue, | |
184 Ptr<NetDeviceQueueInterface> ndqi, | |
185 uint8_t txq, Ptr<const Item> item); | |
186 | |
187 /** | |
188 * \brief Perform the actions required by flow control and dynamic queue | |
189 * limits when a packet is dropped before being enqueued in the queue | |
190 * of a netdevice (which likely indicates that the queue is full) | |
191 * | |
192 * \param queue the device queue | |
193 * \param ndqi the NetDeviceQueueInterface object aggregated to the device | |
194 * \param txq the index of the transmission queue associated with the device q
ueue | |
195 * \param item the dropped packet | |
196 * | |
197 * This method must be connected to the "DropBeforeEnqueue" traced callback | |
198 * of a Queue object (through a bound callback) in order for a netdevice to | |
199 * support flow control and dynamic queue limits. | |
200 */ | |
201 template <typename Item> | |
202 static void PacketDiscarded (Ptr<Queue<Item> > queue, | |
203 Ptr<NetDeviceQueueInterface> ndqi, | |
204 uint8_t txq, Ptr<const Item> item); | |
205 | |
206 protected: | |
207 /** | |
208 * \brief Pass messages to the ns-3 logging system | |
209 * | |
210 * \param level the log level | |
211 * \param args a comma separated list of messages to log | |
212 */ | |
213 template <typename... Args> | |
214 static void NsLog (const enum LogLevel level, Args... args); | |
215 | |
216 private: | |
217 /** | |
218 * \brief Pass messages to the ns-3 logging system | |
219 * | |
220 * \param level the log level | |
221 * \param str the messages to log | |
222 */ | |
223 static void DoNsLog (const enum LogLevel level, std::string str); | |
224 | |
225 bool m_stoppedByDevice; //!< True if the queue has been stopped by the
device | |
226 bool m_stoppedByQueueLimits; //!< True if the queue has been stopped by a q
ueue limits object | |
227 Ptr<QueueLimits> m_queueLimits; //!< Queue limits object | |
228 WakeCallback m_wakeCallback; //!< Wake callback | |
229 }; | |
230 | |
231 | |
232 /** | |
233 * \ingroup netdevice | |
234 * | |
235 * \brief Network device transmission queue interface | |
236 * | |
237 * This interface is used by the traffic control layer and by the aggregated | |
238 * device to access the transmission queues of the device. Additionally, through | |
239 * this interface, traffic control aware netdevices can: | |
240 * - set the number of transmission queues | |
241 * - set the method used (by upper layers) to determine the transmission queue | |
242 * in which the netdevice would enqueue a given packet | |
243 * This interface is created and aggregated to a device by the traffic control | |
244 * layer when an Ipv{4,6}Interface is added to the device or a queue disc is | |
245 * installed on the device. | |
246 */ | |
247 class NetDeviceQueueInterface : public Object | |
248 { | |
249 public: | |
250 /** | |
251 * \brief Get the type ID. | |
252 * \return the object TypeId | |
253 */ | |
254 static TypeId GetTypeId (void); | |
255 | |
256 /** | |
257 * \brief Constructor | |
258 * | |
259 * Creates one NetDeviceQueue by default | |
260 */ | |
261 NetDeviceQueueInterface (); | |
262 virtual ~NetDeviceQueueInterface (); | |
263 | |
264 /** | |
265 * \brief Get the i-th transmission queue of the device. | |
266 * | |
267 * \param i the index of the requested queue. | |
268 * \return the i-th transmission queue of the device. | |
269 * | |
270 * The index of the first transmission queue is zero. | |
271 */ | |
272 Ptr<NetDeviceQueue> GetTxQueue (uint8_t i) const; | |
273 | |
274 /** | |
275 * \brief Get the number of device transmission queues. | |
276 * \return the number of device transmission queues. | |
277 */ | |
278 uint8_t GetNTxQueues (void) const; | |
279 | |
280 /** | |
281 * \brief Set the number of device transmission queues to create. | |
282 * \param numTxQueues number of device transmission queues to create. | |
283 * | |
284 * A multi-queue netdevice must call this method from within its | |
285 * NotifyNewAggregate method to set the number of device transmission queues | |
286 * to create. | |
287 */ | |
288 void SetTxQueuesN (uint8_t numTxQueues); | |
289 | |
290 /** | |
291 * \brief Create the device transmission queues. | |
292 * | |
293 * Called by the traffic control layer just after aggregating this netdevice | |
294 * queue interface to the netdevice. | |
295 */ | |
296 void CreateTxQueues (void); | |
297 | |
298 /// Callback invoked to determine the tx queue selected for a given packet | |
299 typedef Callback< uint8_t, Ptr<QueueItem> > SelectQueueCallback; | |
300 | |
301 /** | |
302 * \brief Set the select queue callback. | |
303 * \param cb the callback to set. | |
304 * | |
305 * A multi-queue netdevice must call this method from within its | |
306 * NotifyNewAggregate method to set the select queue callback, i.e., the | |
307 * method used to select a device transmission queue for a given packet. | |
308 */ | |
309 void SetSelectQueueCallback (SelectQueueCallback cb); | |
310 | |
311 /** | |
312 * \brief Get the select queue callback. | |
313 * \return the select queue callback. | |
314 * | |
315 * Called by the traffic control layer to get the select queue callback set | |
316 * by a multi-queue device. | |
317 */ | |
318 SelectQueueCallback GetSelectQueueCallback (void) const; | |
319 | |
320 protected: | |
321 /** | |
322 * \brief Dispose of the object | |
323 */ | |
324 virtual void DoDispose (void); | |
325 | |
326 private: | |
327 std::vector< Ptr<NetDeviceQueue> > m_txQueuesVector; //!< Device transmissio
n queues | |
328 SelectQueueCallback m_selectQueueCallback; //!< Select queue callback | |
329 uint8_t m_numTxQueues; //!< Number of transmission queues to create | |
330 }; | |
331 | |
332 | 42 |
333 /** | 43 /** |
334 * \ingroup netdevice | 44 * \ingroup netdevice |
335 * | 45 * |
336 * \brief Network layer to device interface | 46 * \brief Network layer to device interface |
337 * | 47 * |
338 * This interface defines the API which the IP and ARP | 48 * This interface defines the API which the IP and ARP |
339 * layers need to access to manage an instance of a network device· | 49 * layers need to access to manage an instance of a network device· |
340 * layer. It currently does not support MAC-level· | 50 * layer. It currently does not support MAC-level· |
341 * multicast but this should not be too hard to add by adding | 51 * multicast but this should not be too hard to add by adding |
(...skipping 16 matching lines...) Expand all Loading... |
358 * device such that the layer 3 does not need any modification | 68 * device such that the layer 3 does not need any modification |
359 * to handle new address formats. This means obviously that the | 69 * to handle new address formats. This means obviously that the |
360 * NetDevice class must know about the address format of all potential· | 70 * NetDevice class must know about the address format of all potential· |
361 * layer 3 protocols through its GetMulticast methods: the current | 71 * layer 3 protocols through its GetMulticast methods: the current |
362 * API has been optimized to make it easy to add new MAC protocols, | 72 * API has been optimized to make it easy to add new MAC protocols, |
363 * not to add new layer 3 protocols. | 73 * not to add new layer 3 protocols. |
364 * | 74 * |
365 * Devices aiming to support flow control and dynamic queue limits must perform | 75 * Devices aiming to support flow control and dynamic queue limits must perform |
366 * the following operations: | 76 * the following operations: |
367 * - in the NotifyNewAggregate method | 77 * - in the NotifyNewAggregate method |
368 * + cache the pointer to the netdevice queue interface aggregated to the de
vice | 78 * + cache the pointer to the netdevice queue interface aggregated to the |
369 * + set the number of device transmission queues through the netdevice queu
e | 79 * device |
370 * interface, if the device is multi-queue | 80 * + set the select queue callback through the netdevice queue interface, |
371 * + set the select queue callback through the netdevice queue interface, if | 81 * if the device is multi-queue |
372 * the device is multi-queue | 82 * - anytime before initialization |
373 * - when the device queues have been created | 83 * + set the number of device transmission queues (and optionally create the
m) |
374 * + set the InOrderDequeue attribute of the device queues to true | 84 * through the netdevice queue interface, if the device is multi-queue |
375 * + connect the Enqueue traced callback of the device queues to the | 85 * - when the device queues have been created, invoke |
| 86 * NetDeviceQueueInterface::ConnectQueueTraces, which |
| 87 * + connects the Enqueue traced callback of the device queues to the |
376 * PacketEnqueued static method of the NetDeviceQueue class | 88 * PacketEnqueued static method of the NetDeviceQueue class |
377 * + connect the Dequeue and DropAfterDequeue traced callback of the device | 89 * + connects the Dequeue and DropAfterDequeue traced callback of the device |
378 * queues to the PacketEnqueued static method of the NetDeviceQueue | 90 * queues to the PacketDequeued static method of the NetDeviceQueue |
379 * class | 91 * class |
380 * + connect the DropBeforeEnqueue traced callback of the device queues to | 92 * + connects the DropBeforeEnqueue traced callback of the device queues to |
381 * the PacketEnqueued static method of the NetDeviceQueue class | 93 * the PacketDiscarded static method of the NetDeviceQueue class |
382 */ | 94 */ |
383 class NetDevice : public Object | 95 class NetDevice : public Object |
384 { | 96 { |
385 public: | 97 public: |
386 /** | 98 /** |
387 * \brief Get the type ID. | 99 * \brief Get the type ID. |
388 * \return the object TypeId | 100 * \return the object TypeId |
389 */ | 101 */ |
390 static TypeId GetTypeId (void); | 102 static TypeId GetTypeId (void); |
391 virtual ~NetDevice(); | 103 virtual ~NetDevice(); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 */ | 354 */ |
643 virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb) = 0; | 355 virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb) = 0; |
644 | 356 |
645 /** | 357 /** |
646 * \return true if this interface supports a bridging mode, false otherwise. | 358 * \return true if this interface supports a bridging mode, false otherwise. |
647 */ | 359 */ |
648 virtual bool SupportsSendFrom (void) const = 0; | 360 virtual bool SupportsSendFrom (void) const = 0; |
649 | 361 |
650 }; | 362 }; |
651 | 363 |
652 | |
653 /** | |
654 * Implementation of the templates declared above. | |
655 */ | |
656 | |
657 template <typename... Args> | |
658 void | |
659 NetDeviceQueue::NsLog (const enum LogLevel level, Args... args) | |
660 { | |
661 std::stringstream ss; | |
662 int dummy[sizeof...(Args)] = { (ss << args, 0)... }; | |
663 NS_UNUSED (dummy); | |
664 DoNsLog (level, ss.str ()); | |
665 } | |
666 | |
667 template <typename Item> | |
668 void | |
669 NetDeviceQueue::PacketEnqueued (Ptr<Queue<Item> > queue, | |
670 Ptr<NetDeviceQueueInterface> ndqi, | |
671 uint8_t txq, Ptr<const Item> item) | |
672 { | |
673 // Inform BQL | |
674 ndqi->GetTxQueue (txq)->NotifyQueuedBytes (item->GetSize ()); | |
675 | |
676 uint16_t mtu = ndqi->GetObject<NetDevice> ()->GetMtu (); | |
677 | |
678 // After enqueuing a packet, we need to check whether the queue is able to | |
679 // store another packet. If not, we stop the queue | |
680 | |
681 if ((queue->GetMode () == QueueBase::QUEUE_MODE_PACKETS && | |
682 queue->GetNPackets () >= queue->GetMaxPackets ()) || | |
683 (queue->GetMode () == QueueBase::QUEUE_MODE_BYTES && | |
684 queue->GetNBytes () + mtu > queue->GetMaxBytes ())) | |
685 { | |
686 NsLog (LOG_DEBUG, "The device queue is being stopped (", queue->GetNPacket
s (), | |
687 " packets and ", queue->GetNBytes (), " bytes inside)"); | |
688 ndqi->GetTxQueue (txq)->Stop (); | |
689 } | |
690 } | |
691 | |
692 template <typename Item> | |
693 void | |
694 NetDeviceQueue::PacketDequeued (Ptr<Queue<Item> > queue, | |
695 Ptr<NetDeviceQueueInterface> ndqi, | |
696 uint8_t txq, Ptr<const Item> item) | |
697 { | |
698 // Inform BQL | |
699 ndqi->GetTxQueue (txq)->NotifyTransmittedBytes (item->GetSize ()); | |
700 | |
701 uint16_t mtu = ndqi->GetObject<NetDevice> ()->GetMtu (); | |
702 | |
703 // After dequeuing a packet, if there is room for another packet we | |
704 // call Wake () that ensures that the queue is not stopped and restarts | |
705 // the queue disc if the queue was stopped | |
706 | |
707 if ((queue->GetMode () == QueueBase::QUEUE_MODE_PACKETS && | |
708 queue->GetNPackets () < queue->GetMaxPackets ()) || | |
709 (queue->GetMode () == QueueBase::QUEUE_MODE_BYTES && | |
710 queue->GetNBytes () + mtu <= queue->GetMaxBytes ())) | |
711 { | |
712 ndqi->GetTxQueue (txq)->Wake (); | |
713 } | |
714 } | |
715 | |
716 template <typename Item> | |
717 void | |
718 NetDeviceQueue::PacketDiscarded (Ptr<Queue<Item> > queue, | |
719 Ptr<NetDeviceQueueInterface> ndqi, | |
720 uint8_t txq, Ptr<const Item> item) | |
721 { | |
722 // This method is called when a packet is discarded before being enqueued in t
he | |
723 // device queue, likely because the queue is full. This should not happen if t
he | |
724 // device correctly stops the queue. Anyway, stop the tx queue, so that the up
per | |
725 // layers do not send packets until there is room in the queue again. | |
726 | |
727 NsLog (LOG_ERROR, "BUG! No room in the device queue for the received packet! (
", | |
728 queue->GetNPackets (), " packets and ", queue->GetNBytes (), " bytes in
side)"); | |
729 | |
730 ndqi->GetTxQueue (txq)->Stop (); | |
731 } | |
732 | |
733 } // namespace ns3 | 364 } // namespace ns3 |
734 | 365 |
735 #endif /* NET_DEVICE_H */ | 366 #endif /* NET_DEVICE_H */ |
LEFT | RIGHT |