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::GetTxQueueIndex (void) const |
| 59 { |
| 60 return m_txq; |
| 61 } |
| 62 |
| 63 void |
| 64 QueueDiscItem::SetTxQueueIndex (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 void |
| 117 QueueDiscClass::SetQueueDisc (Ptr<QueueDisc> qd) |
| 118 { |
| 119 NS_LOG_FUNCTION (this); |
| 120 m_queueDisc = qd; |
| 121 } |
| 122 |
| 123 |
| 124 NS_OBJECT_ENSURE_REGISTERED (QueueDisc); |
| 125 |
| 126 TypeId QueueDisc::GetTypeId (void) |
| 127 { |
| 128 static TypeId tid = TypeId ("ns3::QueueDisc") |
| 129 .SetParent<Object> () |
| 130 .SetGroupName ("TrafficControl") |
| 131 .AddAttribute ("Quota", "The maximum number of packets dequeued in a qdisc r
un", |
| 132 UintegerValue (DEFAULT_QUOTA), |
| 133 MakeUintegerAccessor (&QueueDisc::SetQuota, |
| 134 &QueueDisc::GetQuota), |
| 135 MakeUintegerChecker<uint32_t> ()) |
| 136 .AddAttribute ("InternalQueueList", "The list of internal queues.", |
| 137 ObjectVectorValue (), |
| 138 MakeObjectVectorAccessor (&QueueDisc::m_queues), |
| 139 MakeObjectVectorChecker<Queue> ()) |
| 140 .AddAttribute ("PacketFilterList", "The list of packet filters.", |
| 141 ObjectVectorValue (), |
| 142 MakeObjectVectorAccessor (&QueueDisc::m_filters), |
| 143 MakeObjectVectorChecker<PacketFilter> ()) |
| 144 .AddAttribute ("QueueDiscClassList", "The list of queue disc classes.", |
| 145 ObjectVectorValue (), |
| 146 MakeObjectVectorAccessor (&QueueDisc::m_classes), |
| 147 MakeObjectVectorChecker<QueueDiscClass> ()) |
| 148 .AddTraceSource ("Enqueue", "Enqueue a packet in the queue disc", |
| 149 MakeTraceSourceAccessor (&QueueDisc::m_traceEnqueue), |
| 150 "ns3::QueueItem::TracedCallback") |
| 151 .AddTraceSource ("Dequeue", "Dequeue a packet from the queue disc", |
| 152 MakeTraceSourceAccessor (&QueueDisc::m_traceDequeue), |
| 153 "ns3::QueueItem::TracedCallback") |
| 154 .AddTraceSource ("Requeue", "Requeue a packet in the queue disc", |
| 155 MakeTraceSourceAccessor (&QueueDisc::m_traceRequeue), |
| 156 "ns3::QueueItem::TracedCallback") |
| 157 .AddTraceSource ("Drop", "Drop a packet stored in the queue disc", |
| 158 MakeTraceSourceAccessor (&QueueDisc::m_traceDrop), |
| 159 "ns3::QueueItem::TracedCallback") |
| 160 .AddTraceSource ("PacketsInQueue", |
| 161 "Number of packets currently stored in the queue disc", |
| 162 MakeTraceSourceAccessor (&QueueDisc::m_nPackets), |
| 163 "ns3::TracedValueCallback::Uint32") |
| 164 .AddTraceSource ("BytesInQueue", |
| 165 "Number of bytes currently stored in the queue disc", |
| 166 MakeTraceSourceAccessor (&QueueDisc::m_nBytes), |
| 167 "ns3::TracedValueCallback::Uint32") |
| 168 ; |
| 169 return tid; |
| 170 } |
| 171 |
| 172 QueueDisc::QueueDisc () |
| 173 : m_nPackets (0), |
| 174 m_nBytes (0), |
| 175 m_nTotalReceivedPackets (0), |
| 176 m_nTotalReceivedBytes (0), |
| 177 m_nTotalDroppedPackets (0), |
| 178 m_nTotalDroppedBytes (0), |
| 179 m_nTotalRequeuedPackets (0), |
| 180 m_nTotalRequeuedBytes (0), |
| 181 m_running (false), |
| 182 m_InitCompleted (false) |
| 183 { |
| 184 NS_LOG_FUNCTION (this); |
| 185 } |
| 186 |
| 187 void |
| 188 QueueDisc::DoDispose (void) |
| 189 { |
| 190 NS_LOG_FUNCTION (this); |
| 191 m_queues.clear (); |
| 192 m_filters.clear (); |
| 193 m_classes.clear (); |
| 194 m_device = 0; |
| 195 m_requeued = 0; |
| 196 Object::DoDispose (); |
| 197 } |
| 198 |
| 199 void |
| 200 QueueDisc::Init (void) |
| 201 { |
| 202 if (!m_InitCompleted) |
| 203 { |
| 204 // Check the configuration and initialize the parameters of this queue dis
c |
| 205 NS_ASSERT_MSG (CheckConfig (), "The queue disc configuration is not correc
t"); |
| 206 InitializeParams (); |
| 207 m_InitCompleted = true; |
| 208 } |
| 209 |
| 210 // Check the configuration and initialize the parameters of the child queue di
scs |
| 211 for (std::vector<Ptr<QueueDiscClass> >::iterator cl = m_classes.begin (); |
| 212 cl != m_classes.end (); cl++) |
| 213 { |
| 214 (*cl)->GetQueueDisc ()->Init (); |
| 215 } |
| 216 } |
| 217 |
| 218 uint32_t |
| 219 QueueDisc::GetNPackets () const |
| 220 { |
| 221 NS_LOG_FUNCTION (this); |
| 222 return m_nPackets; |
| 223 } |
| 224 |
| 225 uint32_t |
| 226 QueueDisc::GetNBytes (void) const |
| 227 { |
| 228 NS_LOG_FUNCTION (this); |
| 229 return m_nBytes; |
| 230 } |
| 231 |
| 232 uint32_t |
| 233 QueueDisc::GetTotalReceivedPackets (void) const |
| 234 { |
| 235 NS_LOG_FUNCTION (this); |
| 236 return m_nTotalReceivedPackets; |
| 237 } |
| 238 |
| 239 uint32_t |
| 240 QueueDisc::GetTotalReceivedBytes (void) const |
| 241 { |
| 242 NS_LOG_FUNCTION (this); |
| 243 return m_nTotalReceivedBytes; |
| 244 } |
| 245 |
| 246 uint32_t |
| 247 QueueDisc::GetTotalDroppedPackets (void) const |
| 248 { |
| 249 NS_LOG_FUNCTION (this); |
| 250 return m_nTotalDroppedPackets; |
| 251 } |
| 252 |
| 253 uint32_t |
| 254 QueueDisc:: GetTotalDroppedBytes (void) const |
| 255 { |
| 256 NS_LOG_FUNCTION (this); |
| 257 return m_nTotalDroppedBytes; |
| 258 } |
| 259 |
| 260 uint32_t |
| 261 QueueDisc::GetTotalRequeuedPackets (void) const |
| 262 { |
| 263 NS_LOG_FUNCTION (this); |
| 264 return m_nTotalRequeuedPackets; |
| 265 } |
| 266 |
| 267 uint32_t |
| 268 QueueDisc:: GetTotalRequeuedBytes (void) const |
| 269 { |
| 270 NS_LOG_FUNCTION (this); |
| 271 return m_nTotalRequeuedBytes; |
| 272 } |
| 273 |
| 274 void |
| 275 QueueDisc::SetNetDevice (Ptr<NetDevice> device) |
| 276 { |
| 277 NS_LOG_FUNCTION (this << device); |
| 278 m_device = device; |
| 279 } |
| 280 |
| 281 Ptr<NetDevice> |
| 282 QueueDisc::GetNetDevice (void) const |
| 283 { |
| 284 NS_LOG_FUNCTION (this); |
| 285 return m_device; |
| 286 } |
| 287 |
| 288 void |
| 289 QueueDisc::SetQuota (const uint32_t quota) |
| 290 { |
| 291 NS_LOG_FUNCTION (this << quota); |
| 292 m_quota = quota; |
| 293 } |
| 294 |
| 295 uint32_t |
| 296 QueueDisc::GetQuota (void) const |
| 297 { |
| 298 NS_LOG_FUNCTION (this); |
| 299 return m_quota; |
| 300 } |
| 301 |
| 302 void |
| 303 QueueDisc::AddInternalQueue (Ptr<Queue> queue) |
| 304 { |
| 305 NS_LOG_FUNCTION (this); |
| 306 m_queues.push_back (queue); |
| 307 } |
| 308 |
| 309 Ptr<Queue> |
| 310 QueueDisc::GetInternalQueue (uint32_t i) const |
| 311 { |
| 312 NS_ASSERT (i < m_queues.size ()); |
| 313 return m_queues[i]; |
| 314 } |
| 315 |
| 316 uint32_t |
| 317 QueueDisc::GetNInternalQueues (void) const |
| 318 { |
| 319 return m_queues.size (); |
| 320 } |
| 321 |
| 322 void |
| 323 QueueDisc::AddPacketFilter (Ptr<PacketFilter> filter) |
| 324 { |
| 325 NS_LOG_FUNCTION (this); |
| 326 m_filters.push_back (filter); |
| 327 } |
| 328 |
| 329 Ptr<PacketFilter> |
| 330 QueueDisc::GetPacketFilter (uint32_t i) const |
| 331 { |
| 332 NS_ASSERT (i < m_filters.size ()); |
| 333 return m_filters[i]; |
| 334 } |
| 335 |
| 336 uint32_t |
| 337 QueueDisc::GetNPacketFilters (void) const |
| 338 { |
| 339 return m_filters.size (); |
| 340 } |
| 341 |
| 342 void |
| 343 QueueDisc::AddQueueDiscClass (Ptr<QueueDiscClass> qdClass) |
| 344 { |
| 345 NS_LOG_FUNCTION (this); |
| 346 NS_ABORT_MSG_IF (qdClass->GetQueueDisc () == 0, "Cannot add a class with no at
tached queue disc"); |
| 347 m_classes.push_back (qdClass); |
| 348 } |
| 349 |
| 350 Ptr<QueueDiscClass> |
| 351 QueueDisc::GetQueueDiscClass (uint32_t i) const |
| 352 { |
| 353 NS_ASSERT (i < m_classes.size ()); |
| 354 return m_classes[i]; |
| 355 } |
| 356 |
| 357 uint32_t |
| 358 QueueDisc::GetNQueueDiscClasses (void) const |
| 359 { |
| 360 return m_classes.size (); |
| 361 } |
| 362 |
| 363 int32_t |
| 364 QueueDisc::Classify (Ptr<QueueDiscItem> item) |
| 365 { |
| 366 NS_LOG_FUNCTION (this << item); |
| 367 |
| 368 int32_t ret = PacketFilter::PF_NO_MATCH; |
| 369 for (std::vector<Ptr<PacketFilter> >::iterator f = m_filters.begin (); |
| 370 f != m_filters.end () && ret == PacketFilter::PF_NO_MATCH; f++) |
| 371 { |
| 372 ret = (*f)->Classify (item); |
| 373 } |
| 374 return ret; |
| 375 } |
| 376 |
| 377 QueueDisc::WakeMode |
| 378 QueueDisc::GetWakeMode (void) |
| 379 { |
| 380 return WAKE_ROOT; |
| 381 } |
| 382 |
| 383 void |
| 384 QueueDisc::Drop (Ptr<QueueDiscItem> item) |
| 385 { |
| 386 NS_LOG_FUNCTION (this << item); |
| 387 NS_ASSERT_MSG (m_nPackets >= 1u, "No packet in the queue disc, cannot drop"); |
| 388 NS_ASSERT_MSG (m_nBytes >= item->GetPacketSize (), "The size of the packet tha
t" |
| 389 << " is reported to be dropped is greater than the amount of by
tes" |
| 390 << "stored in the queue disc"); |
| 391 |
| 392 m_nPackets--; |
| 393 m_nBytes -= item->GetPacketSize (); |
| 394 m_nTotalDroppedPackets++; |
| 395 m_nTotalDroppedBytes += item->GetPacketSize (); |
| 396 |
| 397 NS_LOG_LOGIC ("m_traceDrop (p)"); |
| 398 m_traceDrop (item); |
| 399 } |
| 400 |
| 401 bool |
| 402 QueueDisc::Enqueue (Ptr<QueueDiscItem> item) |
| 403 { |
| 404 NS_LOG_FUNCTION (this << item); |
| 405 |
| 406 m_nPackets++; |
| 407 m_nBytes += item->GetPacketSize (); |
| 408 m_nTotalReceivedPackets++; |
| 409 m_nTotalReceivedBytes += item->GetPacketSize (); |
| 410 |
| 411 NS_LOG_LOGIC ("m_traceEnqueue (p)"); |
| 412 m_traceEnqueue (item); |
| 413 |
| 414 return DoEnqueue (item); |
| 415 } |
| 416 |
| 417 Ptr<QueueDiscItem> |
| 418 QueueDisc::Dequeue (void) |
| 419 { |
| 420 NS_LOG_FUNCTION (this); |
| 421 |
| 422 Ptr<QueueDiscItem> item; |
| 423 item = DoDequeue (); |
| 424 |
| 425 if (item != 0) |
| 426 { |
| 427 m_nPackets--; |
| 428 m_nBytes -= item->GetPacketSize (); |
| 429 |
| 430 NS_LOG_LOGIC ("m_traceDequeue (p)"); |
| 431 m_traceDequeue (item); |
| 432 } |
| 433 |
| 434 return item; |
| 435 } |
| 436 |
| 437 Ptr<const QueueDiscItem> |
| 438 QueueDisc::Peek (void) const |
| 439 { |
| 440 NS_LOG_FUNCTION (this); |
| 441 return DoPeek (); |
| 442 } |
| 443 |
| 444 void |
| 445 QueueDisc::Run (void) |
| 446 { |
| 447 NS_LOG_FUNCTION (this); |
| 448 |
| 449 if (RunBegin ()) |
| 450 { |
| 451 uint32_t quota = m_quota; |
| 452 while (Restart ()) |
| 453 { |
| 454 quota -= 1; |
| 455 if (quota <= 0) |
| 456 { |
| 457 /// \todo netif_schedule (q); |
| 458 break; |
| 459 } |
| 460 } |
| 461 RunEnd (); |
| 462 } |
| 463 } |
| 464 |
| 465 bool |
| 466 QueueDisc::RunBegin (void) |
| 467 { |
| 468 NS_LOG_FUNCTION (this); |
| 469 if (m_running) |
| 470 { |
| 471 return false; |
| 472 } |
| 473 |
| 474 m_running = true; |
| 475 return true; |
| 476 } |
| 477 |
| 478 void |
| 479 QueueDisc::RunEnd (void) |
| 480 { |
| 481 NS_LOG_FUNCTION (this); |
| 482 m_running = false; |
| 483 } |
| 484 |
| 485 bool |
| 486 QueueDisc::Restart (void) |
| 487 { |
| 488 NS_LOG_FUNCTION (this); |
| 489 Ptr<QueueDiscItem> item = DequeuePacket(); |
| 490 if (item == 0) |
| 491 { |
| 492 NS_LOG_LOGIC ("No packet to send"); |
| 493 return false; |
| 494 } |
| 495 |
| 496 return Transmit (item); |
| 497 } |
| 498 |
| 499 Ptr<QueueDiscItem> |
| 500 QueueDisc::DequeuePacket () |
| 501 { |
| 502 NS_LOG_FUNCTION (this); |
| 503 NS_ASSERT (m_device); |
| 504 Ptr<QueueDiscItem> item; |
| 505 |
| 506 // First check if there is a requeued packet |
| 507 if (m_requeued != 0) |
| 508 { |
| 509 // If the queue where the requeued packet is destined to is not stopped,
return |
| 510 // the requeued packet; otherwise, return an empty packet. |
| 511 if (!m_device->GetTxQueue (m_requeued->GetTxQueueIndex ())->IsStopped ()
) |
| 512 { |
| 513 item = m_requeued; |
| 514 m_requeued = 0; |
| 515 |
| 516 m_nPackets--; |
| 517 m_nBytes -= item->GetPacketSize (); |
| 518 |
| 519 NS_LOG_LOGIC ("m_traceDequeue (p)"); |
| 520 m_traceDequeue (item); |
| 521 } |
| 522 } |
| 523 else |
| 524 { |
| 525 // If the device is multi-queue (actually, Linux checks if the queue disc
has |
| 526 // multiple queues), ask the queue disc to dequeue a packet (a multi-queue
aware |
| 527 // queue disc should try not to dequeue a packet destined to a stopped que
ue). |
| 528 // Otherwise, ask the queue disc to dequeue a packet only if the (unique)
queue |
| 529 // is not stopped. |
| 530 if (m_device->GetTxQueuesN ()>1 || !m_device->GetTxQueue (0)->IsStopped ()
) |
| 531 { |
| 532 item = Dequeue (); |
| 533 // If the item is not null, add the header to the packet. |
| 534 if (item != 0) |
| 535 { |
| 536 item->AddHeader (); |
| 537 } |
| 538 // Here, Linux tries bulk dequeues |
| 539 } |
| 540 } |
| 541 return item; |
| 542 } |
| 543 |
| 544 void |
| 545 QueueDisc::Requeue (Ptr<QueueDiscItem> item) |
| 546 { |
| 547 NS_LOG_FUNCTION (this << item); |
| 548 m_requeued = item; |
| 549 /// \todo netif_schedule (q); |
| 550 |
| 551 m_nPackets++; // it's still part of the queue |
| 552 m_nBytes += item->GetPacketSize (); |
| 553 m_nTotalRequeuedPackets++; |
| 554 m_nTotalRequeuedBytes += item->GetPacketSize (); |
| 555 |
| 556 NS_LOG_LOGIC ("m_traceRequeue (p)"); |
| 557 m_traceRequeue (item); |
| 558 } |
| 559 |
| 560 bool |
| 561 QueueDisc::Transmit (Ptr<QueueDiscItem> item) |
| 562 { |
| 563 NS_LOG_FUNCTION (this << item); |
| 564 NS_ASSERT (m_device); |
| 565 bool ret = false; |
| 566 |
| 567 if (!m_device->GetTxQueue (item->GetTxQueueIndex ())->IsStopped ()) |
| 568 { |
| 569 // send a copy of the packet because the device might add the |
| 570 // MAC header even if the transmission is unsuccessful (see BUG 2284) |
| 571 Ptr<Packet> copy = item->GetPacket ()->Copy (); |
| 572 ret = m_device->Send (copy, item->GetAddress (), item->GetProtocol ()); |
| 573 } |
| 574 |
| 575 // If the transmission did not happen or failed, requeue the item |
| 576 if (!ret) |
| 577 { |
| 578 Requeue (item); |
| 579 } |
| 580 |
| 581 // If the transmission succeeded but now the queue is stopped, return false |
| 582 if (ret && m_device->GetTxQueue (item->GetTxQueueIndex ())->IsStopped ()) |
| 583 { |
| 584 ret = false; |
| 585 } |
| 586 |
| 587 return ret; |
| 588 } |
| 589 |
| 590 } // namespace ns3 |
OLD | NEW |