Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2007, 2014 University of Washington | |
4 * 2015 Universita' degli Studi di Napoli Federico II | |
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 "ns3/log.h" | |
21 #include "ns3/abort.h" | |
22 #include "ns3/uinteger.h" | |
23 #include "ns3/pointer.h" | |
24 #include "ns3/object-vector.h" | |
25 #include "ns3/packet.h" | |
26 #include "queue-disc.h" | |
27 | |
28 namespace ns3 { | |
29 | |
30 NS_LOG_COMPONENT_DEFINE ("QueueDisc"); | |
31 | |
32 QueueDiscItem::QueueDiscItem (Ptr<Packet> p, const Address& addr, uint16_t proto col) | |
33 : QueueItem (p), | |
34 m_address (addr), | |
35 m_protocol (protocol), | |
36 m_txq (0) | |
37 { | |
38 } | |
39 | |
40 QueueDiscItem::~QueueDiscItem() | |
41 { | |
42 NS_LOG_FUNCTION (this); | |
43 } | |
44 | |
45 Address | |
46 QueueDiscItem::GetAddress (void) const | |
47 { | |
48 return m_address; | |
49 } | |
50 | |
51 uint16_t | |
52 QueueDiscItem::GetProtocol (void) const | |
53 { | |
54 return m_protocol; | |
55 } | |
56 | |
57 uint8_t | |
58 QueueDiscItem::GetTxq (void) const | |
59 { | |
60 return m_txq; | |
61 } | |
62 | |
63 void | |
64 QueueDiscItem::SetTxq (uint8_t txq) | |
65 { | |
66 m_txq = txq; | |
67 } | |
68 | |
69 void | |
70 QueueDiscItem::Print (std::ostream& os) const | |
71 { | |
72 os << GetPacket () << " " | |
73 << "Dst addr " << m_address << " " | |
74 << "proto " << (uint16_t) m_protocol << " " | |
75 << "txq " << (uint8_t) m_txq | |
76 ; | |
77 } | |
78 | |
79 | |
80 NS_OBJECT_ENSURE_REGISTERED (QueueDiscClass); | |
81 | |
82 TypeId QueueDiscClass::GetTypeId (void) | |
83 { | |
84 static TypeId tid = TypeId ("ns3::QueueDiscClass") | |
85 .SetParent<Object> () | |
86 .SetGroupName ("TrafficControl") | |
87 .AddConstructor<QueueDiscClass> () | |
88 .AddAttribute ("QueueDisc", "The queue disc attached to the class", | |
89 PointerValue (), | |
90 MakePointerAccessor (&QueueDiscClass::m_queueDisc), | |
91 MakePointerChecker<QueueDisc> ()) | |
92 ; | |
93 return tid; | |
94 } | |
95 | |
96 QueueDiscClass::QueueDiscClass() | |
97 { | |
98 NS_LOG_FUNCTION (this); | |
99 } | |
100 | |
101 void | |
102 QueueDiscClass::DoDispose (void) | |
103 { | |
104 NS_LOG_FUNCTION (this); | |
105 m_queueDisc = 0; | |
106 Object::DoDispose (); | |
107 } | |
108 | |
109 Ptr<QueueDisc> | |
110 QueueDiscClass::GetQueueDisc (void) const | |
111 { | |
112 NS_LOG_FUNCTION (this); | |
113 return m_queueDisc; | |
114 } | |
115 | |
116 | |
117 NS_OBJECT_ENSURE_REGISTERED (QueueDisc); | |
118 | |
119 TypeId QueueDisc::GetTypeId (void) | |
120 { | |
121 static TypeId tid = TypeId ("ns3::QueueDisc") | |
122 .SetParent<Object> () | |
123 .SetGroupName ("TrafficControl") | |
124 .AddAttribute ("Quota", "The maximum number of packets dequeued in a qdisc r un", | |
125 UintegerValue (DEFAULT_QUOTA), | |
126 MakeUintegerAccessor (&QueueDisc::SetQuota, | |
127 &QueueDisc::GetQuota), | |
128 MakeUintegerChecker<uint32_t> ()) | |
129 .AddAttribute ("InternalQueueList", "The list of internal queues.", | |
130 ObjectVectorValue (), | |
131 MakeObjectVectorAccessor (&QueueDisc::m_queues), | |
132 MakeObjectVectorChecker<Queue> ()) | |
133 .AddAttribute ("PacketFilterList", "The list of packet filters.", | |
134 ObjectVectorValue (), | |
135 MakeObjectVectorAccessor (&QueueDisc::m_filters), | |
136 MakeObjectVectorChecker<PacketFilter> ()) | |
137 .AddAttribute ("QueueDiscClassList", "The list of queue disc classes.", | |
138 ObjectVectorValue (), | |
139 MakeObjectVectorAccessor (&QueueDisc::m_classes), | |
140 MakeObjectVectorChecker<QueueDiscClass> ()) | |
141 .AddTraceSource ("Enqueue", "Enqueue a packet in the queue disc", | |
142 MakeTraceSourceAccessor (&QueueDisc::m_traceEnqueue), | |
143 "ns3::QueueItem::TracedCallback") | |
144 .AddTraceSource ("Dequeue", "Dequeue a packet from the queue disc", | |
145 MakeTraceSourceAccessor (&QueueDisc::m_traceDequeue), | |
146 "ns3::QueueItem::TracedCallback") | |
147 .AddTraceSource ("Requeue", "Requeue a packet in the queue disc", | |
148 MakeTraceSourceAccessor (&QueueDisc::m_traceRequeue), | |
149 "ns3::QueueItem::TracedCallback") | |
150 .AddTraceSource ("Drop", "Drop a packet stored in the queue disc", | |
151 MakeTraceSourceAccessor (&QueueDisc::m_traceDrop), | |
152 "ns3::QueueItem::TracedCallback") | |
153 .AddTraceSource ("PacketsInQueue", | |
154 "Number of packets currently stored in the queue disc", | |
155 MakeTraceSourceAccessor (&QueueDisc::m_nPackets), | |
156 "ns3::TracedValueCallback::Uint32") | |
157 .AddTraceSource ("BytesInQueue", | |
158 "Number of bytes currently stored in the queue disc", | |
159 MakeTraceSourceAccessor (&QueueDisc::m_nBytes), | |
160 "ns3::TracedValueCallback::Uint32") | |
161 ; | |
162 return tid; | |
163 } | |
164 | |
165 QueueDisc::QueueDisc () | |
166 : m_nPackets (0), | |
167 m_nBytes (0), | |
168 m_nTotalReceivedPackets (0), | |
169 m_nTotalReceivedBytes (0), | |
170 m_nTotalDroppedPackets (0), | |
171 m_nTotalDroppedBytes (0), | |
172 m_nTotalRequeuedPackets (0), | |
173 m_nTotalRequeuedBytes (0), | |
174 m_running (false), | |
175 m_InitCompleted (false) | |
176 { | |
177 NS_LOG_FUNCTION (this); | |
178 } | |
179 | |
180 void | |
181 QueueDisc::DoDispose (void) | |
182 { | |
183 NS_LOG_FUNCTION (this); | |
184 m_queues.clear (); | |
185 m_filters.clear (); | |
186 m_classes.clear (); | |
187 m_device = 0; | |
188 m_requeued = 0; | |
189 Object::DoDispose (); | |
190 } | |
191 | |
192 uint32_t | |
193 QueueDisc::GetNPackets () const | |
194 { | |
195 NS_LOG_FUNCTION (this); | |
196 return m_nPackets; | |
197 } | |
198 | |
199 uint32_t | |
200 QueueDisc::GetNBytes (void) const | |
201 { | |
202 NS_LOG_FUNCTION (this); | |
203 return m_nBytes; | |
204 } | |
205 | |
206 uint32_t | |
207 QueueDisc::GetTotalReceivedPackets (void) const | |
208 { | |
209 NS_LOG_FUNCTION (this); | |
210 return m_nTotalReceivedPackets; | |
211 } | |
212 | |
213 uint32_t | |
214 QueueDisc::GetTotalReceivedBytes (void) const | |
215 { | |
216 NS_LOG_FUNCTION (this); | |
217 return m_nTotalReceivedBytes; | |
218 } | |
219 | |
220 uint32_t | |
221 QueueDisc::GetTotalDroppedPackets (void) const | |
222 { | |
223 NS_LOG_FUNCTION (this); | |
224 return m_nTotalDroppedPackets; | |
225 } | |
226 | |
227 uint32_t | |
228 QueueDisc:: GetTotalDroppedBytes (void) const | |
229 { | |
230 NS_LOG_FUNCTION (this); | |
231 return m_nTotalDroppedBytes; | |
232 } | |
233 | |
234 uint32_t | |
235 QueueDisc::GetTotalRequeuedPackets (void) const | |
236 { | |
237 NS_LOG_FUNCTION (this); | |
238 return m_nTotalRequeuedPackets; | |
239 } | |
240 | |
241 uint32_t | |
242 QueueDisc:: GetTotalRequeuedBytes (void) const | |
243 { | |
244 NS_LOG_FUNCTION (this); | |
245 return m_nTotalRequeuedBytes; | |
246 } | |
247 | |
248 void | |
249 QueueDisc::SetNetDevice (Ptr<NetDevice> device) | |
250 { | |
251 NS_LOG_FUNCTION (this << device); | |
252 m_device = device; | |
253 } | |
254 | |
255 Ptr<NetDevice> | |
256 QueueDisc::GetNetDevice (void) const | |
257 { | |
258 NS_LOG_FUNCTION (this); | |
259 return m_device; | |
260 } | |
261 | |
262 void | |
263 QueueDisc::SetQuota (const uint32_t quota) | |
264 { | |
265 NS_LOG_FUNCTION (this << quota); | |
266 m_quota = quota; | |
267 } | |
268 | |
269 uint32_t | |
270 QueueDisc::GetQuota (void) const | |
271 { | |
272 NS_LOG_FUNCTION (this); | |
273 return m_quota; | |
274 } | |
275 | |
276 void | |
277 QueueDisc::AddInternalQueue (Ptr<Queue> queue) | |
278 { | |
279 NS_LOG_FUNCTION (this); | |
280 m_queues.push_back (queue); | |
281 } | |
282 | |
283 Ptr<Queue> | |
284 QueueDisc::GetInternalQueue (uint32_t i) const | |
285 { | |
286 NS_ASSERT (i < m_queues.size ()); | |
287 return m_queues[i]; | |
288 } | |
289 | |
290 uint32_t | |
291 QueueDisc::GetNInternalQueues (void) const | |
292 { | |
293 return m_queues.size (); | |
294 } | |
295 | |
296 void | |
297 QueueDisc::AddPacketFilter (Ptr<PacketFilter> filter) | |
298 { | |
299 NS_LOG_FUNCTION (this); | |
300 m_filters.push_back (filter); | |
301 } | |
302 | |
303 Ptr<PacketFilter> | |
304 QueueDisc::GetPacketFilter (uint32_t i) const | |
305 { | |
306 NS_ASSERT (i < m_filters.size ()); | |
307 return m_filters[i]; | |
308 } | |
309 | |
310 uint32_t | |
311 QueueDisc::GetNPacketFilters (void) const | |
312 { | |
313 return m_filters.size (); | |
314 } | |
315 | |
316 void | |
317 QueueDisc::AddQueueDiscClass (Ptr<QueueDiscClass> qdClass) | |
318 { | |
319 NS_LOG_FUNCTION (this); | |
320 NS_ABORT_MSG_IF (qdClass->GetQueueDisc () == 0, "Cannot add a class with no at tached queue disc"); | |
321 m_classes.push_back (qdClass); | |
322 } | |
323 | |
324 Ptr<QueueDiscClass> | |
325 QueueDisc::GetQueueDiscClass (uint32_t i) const | |
326 { | |
327 NS_ASSERT (i < m_classes.size ()); | |
328 return m_classes[i]; | |
329 } | |
330 | |
331 uint32_t | |
332 QueueDisc::GetNQueueDiscClasses (void) const | |
333 { | |
334 return m_classes.size (); | |
335 } | |
336 | |
337 int32_t | |
338 QueueDisc::Classify (Ptr<QueueDiscItem> item) | |
339 { | |
340 NS_LOG_FUNCTION (this << item); | |
341 | |
342 int32_t ret = PF_NO_MATCH; | |
343 for (std::vector<Ptr<PacketFilter> >::iterator f = m_filters.begin (); | |
344 f != m_filters.end () && ret == PF_NO_MATCH; f++) | |
345 { | |
346 ret = (*f)->Classify (item); | |
347 } | |
348 return ret; | |
349 } | |
350 | |
351 QueueDisc::WakeMode | |
352 QueueDisc::GetWakeMode (void) | |
353 { | |
354 return WAKE_ROOT; | |
355 } | |
356 | |
357 void | |
358 QueueDisc::Drop (Ptr<QueueDiscItem> item) | |
Tommaso Pecorella
2016/02/19 00:51:13
What does it happens if one sub-class goes nuts ?
Stefano Avallone
2016/02/21 23:25:57
Done.
| |
359 { | |
360 NS_LOG_FUNCTION (this << item); | |
361 | |
362 m_nPackets--; | |
363 m_nBytes -= item->GetPacketSize (); | |
364 m_nTotalDroppedPackets++; | |
365 m_nTotalDroppedBytes += item->GetPacketSize (); | |
366 | |
367 NS_LOG_LOGIC ("m_traceDrop (p)"); | |
368 m_traceDrop (item); | |
369 } | |
370 | |
371 bool | |
372 QueueDisc::Enqueue (Ptr<QueueDiscItem> item) | |
373 { | |
374 NS_LOG_FUNCTION (this << item); | |
375 | |
376 if (!m_InitCompleted) | |
377 { | |
378 NS_ASSERT_MSG (CheckConfig (), "The queue disc configuration is not correc t"); | |
379 InitializeParams (); | |
380 m_InitCompleted = true; | |
381 } | |
Tommaso Pecorella
2016/02/19 00:51:13
Just a note: I guess there's no way to avoid this
Stefano Avallone
2016/02/21 23:25:57
Because queue discs are created one piece at a tim
| |
382 | |
383 m_nPackets++; | |
384 m_nBytes += item->GetPacketSize (); | |
385 m_nTotalReceivedPackets++; | |
386 m_nTotalReceivedBytes += item->GetPacketSize (); | |
387 | |
388 NS_LOG_LOGIC ("m_traceEnqueue (p)"); | |
389 m_traceEnqueue (item); | |
390 | |
391 return DoEnqueue (item); | |
392 } | |
393 | |
394 Ptr<QueueDiscItem> | |
395 QueueDisc::Dequeue (void) | |
396 { | |
397 NS_LOG_FUNCTION (this); | |
398 | |
399 Ptr<QueueDiscItem> item; | |
400 item = DoDequeue (); | |
401 | |
402 if (item != 0) | |
403 { | |
404 m_nPackets--; | |
405 m_nBytes -= item->GetPacketSize (); | |
406 | |
407 NS_LOG_LOGIC ("m_traceDequeue (p)"); | |
408 m_traceDequeue (item); | |
409 } | |
410 | |
411 return item; | |
412 } | |
413 | |
414 Ptr<const QueueDiscItem> | |
415 QueueDisc::Peek (void) const | |
416 { | |
417 NS_LOG_FUNCTION (this); | |
418 return DoPeek (); | |
419 } | |
420 | |
421 void | |
422 QueueDisc::Run (void) | |
423 { | |
424 NS_LOG_FUNCTION (this); | |
425 | |
426 if (RunBegin ()) | |
427 { | |
428 uint32_t quota = m_quota; | |
429 while (Restart ()) | |
430 { | |
431 quota -= 1; | |
432 if (quota <= 0) | |
433 { | |
434 /// \todo netif_schedule (q); | |
435 break; | |
436 } | |
437 } | |
438 RunEnd (); | |
439 } | |
440 } | |
441 | |
442 bool | |
443 QueueDisc::RunBegin (void) | |
444 { | |
445 NS_LOG_FUNCTION (this); | |
446 if (m_running) | |
447 { | |
448 return false; | |
449 } | |
450 | |
451 m_running = true; | |
452 return true; | |
453 } | |
454 | |
455 void | |
456 QueueDisc::RunEnd (void) | |
457 { | |
458 NS_LOG_FUNCTION (this); | |
459 m_running = false; | |
460 } | |
461 | |
462 bool | |
463 QueueDisc::Restart (void) | |
464 { | |
465 NS_LOG_FUNCTION (this); | |
466 Ptr<QueueDiscItem> item = DequeuePacket(); | |
467 if (item == 0) | |
468 { | |
469 NS_LOG_LOGIC ("No packet to send"); | |
470 return false; | |
471 } | |
472 | |
473 return Transmit (item); | |
474 } | |
475 | |
476 Ptr<QueueDiscItem> | |
477 QueueDisc::DequeuePacket () | |
478 { | |
479 NS_LOG_FUNCTION (this); | |
480 NS_ASSERT (m_device); | |
481 Ptr<QueueDiscItem> item; | |
482 | |
483 // First check if there is a requeued packet | |
484 if (m_requeued != 0) | |
485 { | |
486 // If the queue where the requeued packet is destined to is not stopped, return | |
487 // the requeued packet; otherwise, return an empty packet. | |
488 if (!m_device->GetTxQueue (m_requeued->GetTxq ())->IsStopped ()) | |
489 { | |
490 item = m_requeued; | |
491 m_requeued = 0; | |
492 | |
493 m_nPackets--; | |
494 m_nBytes -= item->GetPacketSize (); | |
495 | |
496 NS_LOG_LOGIC ("m_traceDequeue (p)"); | |
497 m_traceDequeue (item); | |
498 } | |
499 } | |
500 else | |
501 { | |
502 // If the device is multi-queue (actually, Linux checks if the queue disc has | |
503 // multiple queues), ask the queue disc to dequeue a packet (a multi-queue aware | |
504 // queue disc should try not to dequeue a packet destined to a stopped que ue). | |
505 // Otherwise, ask the queue disc to dequeue a packet only if the (unique) queue | |
506 // is not stopped. | |
507 if (m_device->GetTxQueuesN ()>1 || !m_device->GetTxQueue (0)->IsStopped () ) | |
508 { | |
509 item = Dequeue (); | |
Tommaso Pecorella
2016/02/19 00:51:13
What happens if there are multiple Tx queues and t
Stefano Avallone
2016/02/21 23:25:57
Correct. Also, if the Dequeue (actually, the DoDeq
| |
510 // If the item is not null, add the header to the packet. | |
511 if (item != 0) | |
512 { | |
513 item->AddHeader (); | |
514 } | |
515 // Here, Linux tries bulk dequeues | |
516 } | |
517 } | |
518 return item; | |
519 } | |
520 | |
521 void | |
522 QueueDisc::Requeue (Ptr<QueueDiscItem> item) | |
523 { | |
524 NS_LOG_FUNCTION (this << item); | |
525 m_requeued = item; | |
526 /// \todo netif_schedule (q); | |
527 | |
528 m_nPackets++; // it's still part of the queue | |
529 m_nBytes += item->GetPacketSize (); | |
530 m_nTotalRequeuedPackets++; | |
531 m_nTotalRequeuedBytes += item->GetPacketSize (); | |
532 | |
533 NS_LOG_LOGIC ("m_traceRequeue (p)"); | |
534 m_traceRequeue (item); | |
535 } | |
536 | |
537 bool | |
538 QueueDisc::Transmit (Ptr<QueueDiscItem> item) | |
539 { | |
540 NS_LOG_FUNCTION (this << item); | |
541 NS_ASSERT (m_device); | |
542 bool ret = false; | |
543 | |
544 if (!m_device->GetTxQueue (item->GetTxq ())->IsStopped ()) | |
545 { | |
546 // send a copy of the packet because the device might add the | |
547 // MAC header even if the transmission is unsuccessful (see BUG 2284) | |
548 Ptr<Packet> copy = item->GetPacket ()->Copy (); | |
549 ret = m_device->Send (copy, item->GetAddress (), item->GetProtocol ()); | |
550 } | |
551 | |
552 // If the transmission did not happen or failed, requeue the item | |
553 if (!ret) | |
554 { | |
555 Requeue (item); | |
556 } | |
557 | |
558 // If the transmission succeeded but now the queue is stopped, return false | |
559 if (ret && m_device->GetTxQueue (item->GetTxq ())->IsStopped ()) | |
560 { | |
561 ret = false; | |
562 } | |
563 | |
564 return ret; | |
565 } | |
566 | |
567 } // namespace ns3 | |
OLD | NEW |