From eb0351dccb52229f7d2a7b1304b271fe4dadae74 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 14 Sep 2017 18:12:34 +0200 Subject: [PATCH] traffic-control: Record reasons for dropping and marking packets --- CHANGES.html | 32 +- .../traffic-control/red-vs-fengadaptive.cc | 10 +- examples/traffic-control/red-vs-nlred.cc | 10 +- examples/traffic-control/traffic-control.cc | 2 +- src/traffic-control/doc/queue-discs.rst | 6 + .../examples/adaptive-red-tests.cc | 12 +- src/traffic-control/examples/pie-example.cc | 10 +- src/traffic-control/examples/red-tests.cc | 16 +- src/traffic-control/examples/red-vs-ared.cc | 10 +- src/traffic-control/model/codel-queue-disc.cc | 33 +- src/traffic-control/model/codel-queue-disc.h | 21 +- .../model/fq-codel-queue-disc.cc | 10 +- .../model/fq-codel-queue-disc.h | 6 +- .../model/pfifo-fast-queue-disc.cc | 2 +- .../model/pfifo-fast-queue-disc.h | 3 + src/traffic-control/model/pie-queue-disc.cc | 15 +- src/traffic-control/model/pie-queue-disc.h | 22 +- src/traffic-control/model/queue-disc.cc | 295 +++++++++++++++++- src/traffic-control/model/queue-disc.h | 99 +++++- src/traffic-control/model/red-queue-disc.cc | 29 +- src/traffic-control/model/red-queue-disc.h | 28 +- .../adaptive-red-queue-disc-test-suite.cc | 49 +-- .../test/codel-queue-disc-test-suite.cc | 19 +- .../test/pie-queue-disc-test-suite.cc | 24 +- .../test/red-queue-disc-test-suite.cc | 77 +++-- 25 files changed, 568 insertions(+), 272 deletions(-) diff --git a/CHANGES.html b/CHANGES.html index 799e31dfa..681478fb0 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -95,13 +95,33 @@ us a note on ns-developers mailing list.

  • MqQueueDisc, a multi-queue aware queue disc modelled after the mq qdisc in Linux, has been introduced.
  • -
  • Added QueueDisc::GetStats() which returns detailed statistics about the operations of a queue disc. - Consequently, a number of methods of the QueueDisc class have been removed: GetTotalReceivedPackets(), - GetTotalReceivedBytes(), GetTotalDroppedPackets(), GetTotalDroppedBytes(), - GetTotalRequeuedPackets(), GetTotalRequeuedBytes(). -
  • Two new methods, QueueDisc::DropBeforeEnqueue() and QueueDisc::DropAfterDequeue() have - been introduced to replace QueueDisc::Drop(). Correspondingly, two new trace sources have been added to the QueueDisc class: DropBeforeEnqueue and DropAfterDequeue. + been introduced to replace QueueDisc::Drop(). These new methods require the caller to specify the + reason why a packet was dropped. Correspondingly, two new trace sources ("DropBeforeEnqueue" and + "DropAfterDequeue") have been added to the QueueDisc class, providing both the items that were dropped + and the reason why they were dropped. +
  • +
  • Added QueueDisc::GetStats() which returns detailed statistics about the operations of + a queue disc. Statistics can be accessed through the member variables of the returned object and + by calling the GetNDroppedPackets(), GetNDroppedBytes(), GetNMarkedPackets() and GetNMarkedBytes() methods on the returned object. Such methods return the number of packets/bytes + dropped/marked for the specified reason (passed as argument). Consequently: + +
  • +
  • The new QueueDisc::Mark() method has been introduced to allow subclasses to request to mark a packet. + The caller must specify the reason why the packet must be marked. Correspondingly, a new trace source ("Mark") + has been added to the QueueDisc class, providing both the items that were marked and the reason why they + were marked.
  • A new trace source, SojournTime, is exported by the QueueDisc base class to provide the sojourn time of every packet dequeued from a queue disc. This has been made possible by adding a diff --git a/examples/traffic-control/red-vs-fengadaptive.cc b/examples/traffic-control/red-vs-fengadaptive.cc index 818266315..e78e2fa1a 100644 --- a/examples/traffic-control/red-vs-fengadaptive.cc +++ b/examples/traffic-control/red-vs-fengadaptive.cc @@ -165,24 +165,22 @@ int main (int argc, char *argv[]) std::cout << "Running the simulation" << std::endl; Simulator::Run (); - RedQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); - if (st.unforcedDrop == 0) + if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0) { std::cout << "There should be some unforced drops" << std::endl; exit (1); } - if (st.qLimDrop != 0) + if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0) { std::cout << "There should be zero drops due to queue full" << std::endl; exit (1); } std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl; + std::cout << st << std::endl; std::cout << "Destroying the simulation" << std::endl; Simulator::Destroy (); diff --git a/examples/traffic-control/red-vs-nlred.cc b/examples/traffic-control/red-vs-nlred.cc index 6cf3c122b..c04c393de 100644 --- a/examples/traffic-control/red-vs-nlred.cc +++ b/examples/traffic-control/red-vs-nlred.cc @@ -167,24 +167,22 @@ int main (int argc, char *argv[]) std::cout << "Running the simulation" << std::endl; Simulator::Run (); - RedQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); - if (st.unforcedDrop == 0) + if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0) { std::cout << "There should be some unforced drops" << std::endl; exit (1); } - if (st.qLimDrop != 0) + if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0) { std::cout << "There should be zero drops due to queue full" << std::endl; exit (1); } std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl; + std::cout << st << std::endl; std::cout << "Destroying the simulation" << std::endl; Simulator::Destroy (); diff --git a/examples/traffic-control/traffic-control.cc b/examples/traffic-control/traffic-control.cc index 5042b977e..94fca9286 100644 --- a/examples/traffic-control/traffic-control.cc +++ b/examples/traffic-control/traffic-control.cc @@ -81,7 +81,7 @@ DevicePacketsInQueueTrace (uint32_t oldValue, uint32_t newValue) void SojournTimeTrace (Time oldValue, Time newValue) { - std::cout << "Sojourn time " << newValue << std::endl; + std::cout << "Sojourn time " << newValue.ToDouble (Time::MS) << "ms" << std::endl; } int diff --git a/src/traffic-control/doc/queue-discs.rst b/src/traffic-control/doc/queue-discs.rst index fe9e72086..77f9705a7 100644 --- a/src/traffic-control/doc/queue-discs.rst +++ b/src/traffic-control/doc/queue-discs.rst @@ -70,6 +70,12 @@ of the queue disc. The following identities hold: * queued = enqueued - dequeued * sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet) +Separate counters are also kept for each possible reason to drop a packet. +When a packet is dropped by an internal queue, e.g., because the queue is full, +the reason is "Dropped by internal queue". When a packet is dropped by a child +queue disc, the reason is "(Dropped by child queue disc) " followed by the +reason why the child queue disc dropped the packet. + The QueueDisc base class provides the SojournTime trace source, which provides the sojourn time of every packet dequeued from a queue disc, including packets that are dropped or requeued after being dequeued. The sojourn time is taken diff --git a/src/traffic-control/examples/adaptive-red-tests.cc b/src/traffic-control/examples/adaptive-red-tests.cc index d3dc2f15c..3ca033f76 100644 --- a/src/traffic-control/examples/adaptive-red-tests.cc +++ b/src/traffic-control/examples/adaptive-red-tests.cc @@ -479,9 +479,9 @@ main (int argc, char *argv[]) Simulator::Stop (Seconds (sink_stop_time)); Simulator::Run (); - RedQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); - if (st.unforcedDrop == 0) + if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0) { std::cout << "There should be some unforced drops" << std::endl; exit (1); @@ -489,7 +489,7 @@ main (int argc, char *argv[]) if (aredTest == 1 || aredTest == 2 || aredTest == 13) { - if (st.qLimDrop == 0) + if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) == 0) { std::cout << "There should be some drops due to queue full" << std::endl; exit (1); @@ -497,7 +497,7 @@ main (int argc, char *argv[]) } else { - if (st.qLimDrop != 0) + if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0) { std::cout << "There should be zero drops due to queue full" << std::endl; exit (1); @@ -515,9 +515,7 @@ main (int argc, char *argv[]) if (printAredStats) { std::cout << "*** ARED stats from Node 2 queue ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl; + std::cout << st << std::endl; } Simulator::Destroy (); diff --git a/src/traffic-control/examples/pie-example.cc b/src/traffic-control/examples/pie-example.cc index 6f3645967..0c26833f2 100644 --- a/src/traffic-control/examples/pie-example.cc +++ b/src/traffic-control/examples/pie-example.cc @@ -304,9 +304,9 @@ main (int argc, char *argv[]) Simulator::Stop (Seconds (sink_stop_time)); Simulator::Run (); - PieQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); - if (st.forcedDrop != 0) + if (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP) != 0) { std::cout << "There should be no drops due to queue full." << std::endl; exit (1); @@ -323,8 +323,10 @@ main (int argc, char *argv[]) if (printPieStats) { std::cout << "*** PIE stats from Node 2 queue ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due to queue limits" << std::endl; + std::cout << "\t " << st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP) + << " drops due to prob mark" << std::endl; + std::cout << "\t " << st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP) + << " drops due to queue limits" << std::endl; } Simulator::Destroy (); diff --git a/src/traffic-control/examples/red-tests.cc b/src/traffic-control/examples/red-tests.cc index d96ab0f3f..456814f24 100644 --- a/src/traffic-control/examples/red-tests.cc +++ b/src/traffic-control/examples/red-tests.cc @@ -458,17 +458,13 @@ main (int argc, char *argv[]) if (printRedStats) { - RedQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); - std::cout << "*** RED stats from Node 2 queue ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due queue full" << std::endl; + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); + std::cout << "*** RED stats from Node 2 queue disc ***" << std::endl; + std::cout << st << std::endl; - st = StaticCast (queueDiscs.Get (1))->GetStats (); - std::cout << "*** RED stats from Node 3 queue ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due queue full" << std::endl; + st = queueDiscs.Get (1)->GetStats (); + std::cout << "*** RED stats from Node 3 queue disc ***" << std::endl; + std::cout << st << std::endl; } Simulator::Destroy (); diff --git a/src/traffic-control/examples/red-vs-ared.cc b/src/traffic-control/examples/red-vs-ared.cc index 9ff14cdf7..e6213cb7d 100644 --- a/src/traffic-control/examples/red-vs-ared.cc +++ b/src/traffic-control/examples/red-vs-ared.cc @@ -166,24 +166,22 @@ int main (int argc, char *argv[]) std::cout << "Running the simulation" << std::endl; Simulator::Run (); - RedQueueDisc::Stats st = StaticCast (queueDiscs.Get (0))->GetStats (); + QueueDisc::Stats st = queueDiscs.Get (0)->GetStats (); - if (st.unforcedDrop == 0) + if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0) { std::cout << "There should be some unforced drops" << std::endl; exit (1); } - if (st.qLimDrop != 0) + if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0) { std::cout << "There should be zero drops due to queue full" << std::endl; exit (1); } std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl; - std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl; - std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl; - std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl; + std::cout << st << std::endl; std::cout << "Destroying the simulation" << std::endl; Simulator::Destroy (); diff --git a/src/traffic-control/model/codel-queue-disc.cc b/src/traffic-control/model/codel-queue-disc.cc index f151c9f8d..09322cf2c 100644 --- a/src/traffic-control/model/codel-queue-disc.cc +++ b/src/traffic-control/model/codel-queue-disc.cc @@ -109,10 +109,6 @@ TypeId CoDelQueueDisc::GetTypeId (void) "CoDel count", MakeTraceSourceAccessor (&CoDelQueueDisc::m_count), "ns3::TracedValueCallback::Uint32") - .AddTraceSource ("DropCount", - "CoDel drop count", - MakeTraceSourceAccessor (&CoDelQueueDisc::m_dropCount), - "ns3::TracedValueCallback::Uint32") .AddTraceSource ("LastCount", "CoDel lastcount", MakeTraceSourceAccessor (&CoDelQueueDisc::m_lastCount), @@ -134,7 +130,6 @@ CoDelQueueDisc::CoDelQueueDisc () : QueueDisc (), m_maxBytes (), m_count (0), - m_dropCount (0), m_lastCount (0), m_dropping (false), m_recInvSqrt (~0U >> REC_INV_SQRT_SHIFT), @@ -143,8 +138,7 @@ CoDelQueueDisc::CoDelQueueDisc () m_state1 (0), m_state2 (0), m_state3 (0), - m_states (0), - m_dropOverLimit (0) + m_states (0) { NS_LOG_FUNCTION (this); } @@ -192,21 +186,18 @@ bool CoDelQueueDisc::DoEnqueue (Ptr item) { NS_LOG_FUNCTION (this << item); - Ptr p = item->GetPacket (); if (m_mode == QUEUE_DISC_MODE_PACKETS && (GetInternalQueue (0)->GetNPackets () + 1 > m_maxPackets)) { NS_LOG_LOGIC ("Queue full (at max packets) -- dropping pkt"); - DropBeforeEnqueue (item); - ++m_dropOverLimit; + DropBeforeEnqueue (item, OVERLIMIT_DROP); return false; } if (m_mode == QUEUE_DISC_MODE_BYTES && (GetInternalQueue (0)->GetNBytes () + item->GetSize () > m_maxBytes)) { NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- dropping pkt"); - DropBeforeEnqueue (item); - ++m_dropOverLimit; + DropBeforeEnqueue (item, OVERLIMIT_DROP); return false; } @@ -307,9 +298,8 @@ CoDelQueueDisc::DoDequeue (void) // rates so high that the next drop should happen now, // hence the while loop. NS_LOG_LOGIC ("Sojourn time is still above target and it's time for next drop; dropping " << item); - DropAfterDequeue (item); + DropAfterDequeue (item, TARGET_EXCEEDED_DROP); - ++m_dropCount; ++m_count; NewtonStep (); item = GetInternalQueue (0)->Dequeue (); @@ -346,8 +336,7 @@ CoDelQueueDisc::DoDequeue (void) { // Drop the first packet and enter dropping state unless the queue is empty NS_LOG_LOGIC ("Sojourn time goes above target, dropping the first packet " << item << " and entering the dropping state"); - ++m_dropCount; - DropAfterDequeue (item); + DropAfterDequeue (item, TARGET_EXCEEDED_DROP); item = GetInternalQueue (0)->Dequeue (); @@ -405,18 +394,6 @@ CoDelQueueDisc::GetQueueSize (void) } } -uint32_t -CoDelQueueDisc::GetDropOverLimit (void) -{ - return m_dropOverLimit; -} - -uint32_t -CoDelQueueDisc::GetDropCount (void) -{ - return m_dropCount; -} - Time CoDelQueueDisc::GetTarget (void) { diff --git a/src/traffic-control/model/codel-queue-disc.h b/src/traffic-control/model/codel-queue-disc.h index 1f71fb281..5436dea5c 100644 --- a/src/traffic-control/model/codel-queue-disc.h +++ b/src/traffic-control/model/codel-queue-disc.h @@ -108,21 +108,6 @@ public: */ uint32_t GetQueueSize (void); - /** - * \brief Get the number of packets dropped when packets - * arrive at a full queue and cannot be enqueued. - * - * \returns The number of dropped packets - */ - uint32_t GetDropOverLimit (void); - - /** - * \brief Get the number of packets dropped according to CoDel algorithm - * - * \returns The number of dropped packets - */ - uint32_t GetDropCount (void); - /** * \brief Get the target queue delay * @@ -144,6 +129,10 @@ public: */ uint32_t GetDropNext (void); + // Reasons for dropping packets + static constexpr const char* TARGET_EXCEEDED_DROP = "Target exceeded drop"; //!< Sojourn time above target + static constexpr const char* OVERLIMIT_DROP = "Overlimit drop"; //!< Overlimit dropped packet + private: friend class::CoDelQueueDiscNewtonStepTest; // Test code friend class::CoDelQueueDiscControlLawTest; // Test code @@ -242,7 +231,6 @@ private: Time m_interval; //!< 100 ms sliding minimum time window width Time m_target; //!< 5 ms target queue delay TracedValue m_count; //!< Number of packets dropped since entering drop state - TracedValue m_dropCount; //!< Number of dropped packets according CoDel algorithm TracedValue m_lastCount; //!< Last number of packets dropped since entering drop state TracedValue m_dropping; //!< True if in dropping state uint16_t m_recInvSqrt; //!< Reciprocal inverse square root @@ -252,7 +240,6 @@ private: uint32_t m_state2; //!< Number of times we perform next drop while in dropping state uint32_t m_state3; //!< Number of times we enter drop state and drop the fist packet uint32_t m_states; //!< Total number of times we are in state 1, state 2, or state 3 - uint32_t m_dropOverLimit; //!< The number of packets dropped due to full queue QueueDiscMode m_mode; //!< The operating mode (Bytes or packets) }; diff --git a/src/traffic-control/model/fq-codel-queue-disc.cc b/src/traffic-control/model/fq-codel-queue-disc.cc index 674eef47f..d9545c65d 100644 --- a/src/traffic-control/model/fq-codel-queue-disc.cc +++ b/src/traffic-control/model/fq-codel-queue-disc.cc @@ -128,8 +128,7 @@ TypeId FqCoDelQueueDisc::GetTypeId (void) } FqCoDelQueueDisc::FqCoDelQueueDisc () - : m_quantum (0), - m_overlimitDroppedPackets (0) + : m_quantum (0) { NS_LOG_FUNCTION (this); } @@ -162,7 +161,7 @@ FqCoDelQueueDisc::DoEnqueue (Ptr item) if (ret == PacketFilter::PF_NO_MATCH) { NS_LOG_ERROR ("No filter has been able to classify this packet, drop it."); - DropBeforeEnqueue (item); + DropBeforeEnqueue (item, UNCLASSIFIED_DROP); return false; } @@ -387,12 +386,11 @@ FqCoDelQueueDisc::FqCoDelDrop (void) do { - item = qd->GetInternalQueue (0)->Remove (); + item = qd->GetInternalQueue (0)->Dequeue (); + DropAfterDequeue (item, OVERLIMIT_DROP); len += item->GetSize (); } while (++count < m_dropBatchSize && len < threshold); - m_overlimitDroppedPackets += count; - return index; } diff --git a/src/traffic-control/model/fq-codel-queue-disc.h b/src/traffic-control/model/fq-codel-queue-disc.h index 079f25235..4938326cb 100644 --- a/src/traffic-control/model/fq-codel-queue-disc.h +++ b/src/traffic-control/model/fq-codel-queue-disc.h @@ -126,6 +126,10 @@ public: */ uint32_t GetQuantum (void) const; + // Reasons for dropping packets + static constexpr const char* UNCLASSIFIED_DROP = "Unclassified drop"; //!< No packet filter able to classify packet + static constexpr const char* OVERLIMIT_DROP = "Overlimit drop"; //!< Overlimit dropped packets + private: virtual bool DoEnqueue (Ptr item); virtual Ptr DoDequeue (void); @@ -146,8 +150,6 @@ private: uint32_t m_flows; //!< Number of flow queues uint32_t m_dropBatchSize; //!< Max number of packets dropped from the fat flow - uint32_t m_overlimitDroppedPackets; //!< Number of overlimit dropped packets - std::list > m_newFlows; //!< The list of new flows std::list > m_oldFlows; //!< The list of old flows diff --git a/src/traffic-control/model/pfifo-fast-queue-disc.cc b/src/traffic-control/model/pfifo-fast-queue-disc.cc index 3348a4f06..6926f796b 100644 --- a/src/traffic-control/model/pfifo-fast-queue-disc.cc +++ b/src/traffic-control/model/pfifo-fast-queue-disc.cc @@ -68,7 +68,7 @@ PfifoFastQueueDisc::DoEnqueue (Ptr item) if (GetNPackets () >= m_limit) { NS_LOG_LOGIC ("Queue disc limit exceeded -- dropping packet"); - DropBeforeEnqueue (item); + DropBeforeEnqueue (item, LIMIT_EXCEEDED_DROP); return false; } diff --git a/src/traffic-control/model/pfifo-fast-queue-disc.h b/src/traffic-control/model/pfifo-fast-queue-disc.h index 49e163ec9..cf9c3170a 100644 --- a/src/traffic-control/model/pfifo-fast-queue-disc.h +++ b/src/traffic-control/model/pfifo-fast-queue-disc.h @@ -62,6 +62,9 @@ public: virtual ~PfifoFastQueueDisc(); + // Reasons for dropping packets + static constexpr const char* LIMIT_EXCEEDED_DROP = "Queue disc limit exceeded"; //!< Packet dropped due to queue disc limit exceeded + private: /** * Priority to band map. Values are taken from the prio2band array used by diff --git a/src/traffic-control/model/pie-queue-disc.cc b/src/traffic-control/model/pie-queue-disc.cc index dc4a067fe..d341e443b 100644 --- a/src/traffic-control/model/pie-queue-disc.cc +++ b/src/traffic-control/model/pie-queue-disc.cc @@ -164,13 +164,6 @@ PieQueueDisc::GetQueueSize (void) } } -PieQueueDisc::Stats -PieQueueDisc::GetStats () -{ - NS_LOG_FUNCTION (this); - return m_stats; -} - Time PieQueueDisc::GetQueueDelay (void) { @@ -197,15 +190,13 @@ PieQueueDisc::DoEnqueue (Ptr item) || (GetMode () == QUEUE_DISC_MODE_BYTES && nQueued + item->GetSize () > m_queueLimit)) { // Drops due to queue limit: reactive - DropBeforeEnqueue (item); - m_stats.forcedDrop++; + DropBeforeEnqueue (item, FORCED_DROP); return false; } else if (DropEarly (item, nQueued)) { // Early probability drop: proactive - DropBeforeEnqueue (item); - m_stats.unforcedDrop++; + DropBeforeEnqueue (item, UNFORCED_DROP); return false; } @@ -232,8 +223,6 @@ PieQueueDisc::InitializeParams (void) m_dqStart = 0; m_burstState = NO_BURST; m_qDelayOld = Time (Seconds (0)); - m_stats.forcedDrop = 0; - m_stats.unforcedDrop = 0; } bool PieQueueDisc::DropEarly (Ptr item, uint32_t qSize) diff --git a/src/traffic-control/model/pie-queue-disc.h b/src/traffic-control/model/pie-queue-disc.h index 637115455..5ed9256ab 100644 --- a/src/traffic-control/model/pie-queue-disc.h +++ b/src/traffic-control/model/pie-queue-disc.h @@ -67,15 +67,6 @@ public: */ virtual ~PieQueueDisc (); - /** - * \brief Stats - */ - typedef struct - { - uint32_t unforcedDrop; //!< Early probability drops: proactive - uint32_t forcedDrop; //!< Drops due to queue limit: reactive - } Stats; - /** * \brief Burst types */ @@ -131,13 +122,6 @@ public: */ Time GetQueueDelay (void); - /** - * \brief Get PIE statistics after running. - * - * \returns The drop statistics. - */ - Stats GetStats (); - /** * Assign a fixed random variable stream number to the random variables * used by this model. Return the number of streams (possibly zero) that @@ -148,6 +132,10 @@ public: */ int64_t AssignStreams (int64_t stream); + // Reasons for dropping packets + static constexpr const char* UNFORCED_DROP = "Unforced drop"; //!< Early probability drops: proactive + static constexpr const char* FORCED_DROP = "Forced drop"; //!< Drops due to queue limit: reactive + protected: /** * \brief Dispose of the object @@ -180,8 +168,6 @@ private: */ void CalculateP (); - Stats m_stats; //!< PIE statistics - // ** Variables supplied by user QueueDiscMode m_mode; //!< Mode (bytes or packets) uint32_t m_queueLimit; //!< Queue limit in bytes / packets diff --git a/src/traffic-control/model/queue-disc.cc b/src/traffic-control/model/queue-disc.cc index 95f14b516..f025d8e14 100644 --- a/src/traffic-control/model/queue-disc.cc +++ b/src/traffic-control/model/queue-disc.cc @@ -103,13 +103,86 @@ QueueDisc::Stats::Stats () nTotalDroppedBytesBeforeEnqueue (0), nTotalDroppedBytesAfterDequeue (0), nTotalRequeuedPackets (0), - nTotalRequeuedBytes (0) + nTotalRequeuedBytes (0), + nTotalMarkedPackets (0), + nTotalMarkedBytes (0) { } +uint32_t +QueueDisc::Stats::GetNDroppedPackets (std::string reason) const +{ + uint32_t count = 0; + auto it = nDroppedPacketsBeforeEnqueue.find (reason); + + if (it != nDroppedPacketsBeforeEnqueue.end ()) + { + count += it->second; + } + + it = nDroppedPacketsAfterDequeue.find (reason); + + if (it != nDroppedPacketsAfterDequeue.end ()) + { + count += it->second; + } + + return count; +} + +uint64_t +QueueDisc::Stats::GetNDroppedBytes (std::string reason) const +{ + uint64_t count = 0; + auto it = nDroppedBytesBeforeEnqueue.find (reason); + + if (it != nDroppedBytesBeforeEnqueue.end ()) + { + count += it->second; + } + + it = nDroppedBytesAfterDequeue.find (reason); + + if (it != nDroppedBytesAfterDequeue.end ()) + { + count += it->second; + } + + return count; +} + +uint32_t +QueueDisc::Stats::GetNMarkedPackets (std::string reason) const +{ + auto it = nMarkedPackets.find (reason); + + if (it != nMarkedPackets.end ()) + { + return it->second; + } + + return 0; +} + +uint64_t +QueueDisc::Stats::GetNMarkedBytes (std::string reason) const +{ + auto it = nMarkedBytes.find (reason); + + if (it != nMarkedBytes.end ()) + { + return it->second; + } + + return 0; +} + void QueueDisc::Stats::Print (std::ostream &os) const { + std::map::const_iterator itp; + std::map::const_iterator itb; + os << std::endl << "Packets/Bytes received: " << nTotalReceivedPackets << " / " << nTotalReceivedBytes @@ -127,14 +200,59 @@ QueueDisc::Stats::Print (std::ostream &os) const << nTotalDroppedBytes << std::endl << "Packets/Bytes dropped before enqueue: " << nTotalDroppedPacketsBeforeEnqueue << " / " - << nTotalDroppedBytesBeforeEnqueue - << std::endl << "Packets/Bytes dropped after dequeue: " + << nTotalDroppedBytesBeforeEnqueue; + + itp = nDroppedPacketsBeforeEnqueue.begin (); + itb = nDroppedBytesBeforeEnqueue.begin (); + + while (itp != nDroppedPacketsBeforeEnqueue.end () && + itb != nDroppedBytesBeforeEnqueue.end ()) + { + NS_ASSERT (itp->first.compare (itb->first) == 0); + os << std::endl << " " << itp->first << ": " + << itp->second << " / " << itb->second; + itp++; + itb++; + } + + os << std::endl << "Packets/Bytes dropped after dequeue: " << nTotalDroppedPacketsAfterDequeue << " / " - << nTotalDroppedBytesAfterDequeue - << std::endl << "Packets/Bytes sent: " + << nTotalDroppedBytesAfterDequeue; + + itp = nDroppedPacketsAfterDequeue.begin (); + itb = nDroppedBytesAfterDequeue.begin (); + + while (itp != nDroppedPacketsAfterDequeue.end () && + itb != nDroppedBytesAfterDequeue.end ()) + { + NS_ASSERT (itp->first.compare (itb->first) == 0); + os << std::endl << " " << itp->first << ": " + << itp->second << " / " << itb->second; + itp++; + itb++; + } + + os << std::endl << "Packets/Bytes sent: " << nTotalSentPackets << " / " << nTotalSentBytes - << std::endl; + << std::endl << "Packets/Bytes marked: " + << nTotalMarkedPackets << " / " + << nTotalMarkedBytes; + + itp = nMarkedPackets.begin (); + itb = nMarkedBytes.begin (); + + while (itp != nMarkedPackets.end () && + itb != nMarkedBytes.end ()) + { + NS_ASSERT (itp->first.compare (itb->first) == 0); + os << std::endl << " " << itp->first << ": " + << itp->second << " / " << itb->second; + itp++; + itb++; + } + + os << std::endl; } std::ostream & operator << (std::ostream &os, const QueueDisc::Stats &stats) @@ -185,6 +303,9 @@ TypeId QueueDisc::GetTypeId (void) .AddTraceSource ("DropAfterDequeue", "Drop a packet after dequeue", MakeTraceSourceAccessor (&QueueDisc::m_traceDropAfterDequeue), "ns3::QueueDiscItem::TracedCallback") + .AddTraceSource ("Mark", "Mark a packet stored in the queue disc", + MakeTraceSourceAccessor (&QueueDisc::m_traceMark), + "ns3::QueueDiscItem::TracedCallback") .AddTraceSource ("PacketsInQueue", "Number of packets currently stored in the queue disc", MakeTraceSourceAccessor (&QueueDisc::m_nPackets), @@ -208,6 +329,51 @@ QueueDisc::QueueDisc () m_running (false) { NS_LOG_FUNCTION (this); + + using namespace std::placeholders; + + // Remove ambiguity for overloaded member functions + typedef std::basic_string& (std::basic_string::*Function) (const char*); + + Function append = &std::basic_string::append, + assign = &std::basic_string::assign; + + // The operator() of these function objects calls the QueueDisc::DropBeforeEnqueue + // and QueueDisc::DropAfterDequeue methods of this QueueDisc object (these function + // objects are bound to this QueueDisc object), which require two arguments: a + // Ptr and a const char*. Given that a callback to the operator() + // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the Queue + // class, the first argument is provided by such traces, while the second argument + // (the reason why the packet was dropped) is bound to the INTERNAL_QUEUE_DROP constant. + m_internalQueueDbeFunctor = std::bind (&QueueDisc::DropBeforeEnqueue, this, + _1, (const char*)INTERNAL_QUEUE_DROP); + m_internalQueueDadFunctor = std::bind (&QueueDisc::DropAfterDequeue, this, + _1, (const char*)INTERNAL_QUEUE_DROP); + + // The operator() of these function objects calls the QueueDisc::DropBeforeEnqueue + // and QueueDisc::DropAfterDequeue methods of this QueueDisc object (these function + // objects are bound to this QueueDisc object), which require two arguments: a + // Ptr and a const char*. Given that a callback to the operator() + // is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the QueueDisc + // class, both arguments are provided by such traces. The first argument is provided + // as is, while the second argument (the reason why the packet was dropped) is obtained + // by calling m_childQueueDiscDropMsg.assign (CHILD_QUEUE_DISC_DROP).append (_2).data () + // i.e., the second argument is the concatenation of the CHILD_QUEUE_DISC_DROP constant + // and the second argument provided by the traces of the QueueDisc class. + m_childQueueDiscDbeFunctor = std::bind (&QueueDisc::DropBeforeEnqueue, this, _1, + std::bind (&std::basic_string::data, + std::bind (append, + std::bind (assign, + &m_childQueueDiscDropMsg, + (const char*)CHILD_QUEUE_DISC_DROP), + _2))); + m_childQueueDiscDadFunctor = std::bind (&QueueDisc::DropAfterDequeue, this, _1, + std::bind (&std::basic_string::data, + std::bind (append, + std::bind (assign, + &m_childQueueDiscDropMsg, + (const char*)CHILD_QUEUE_DISC_DROP), + _2))); } QueueDisc::~QueueDisc () @@ -320,6 +486,7 @@ void QueueDisc::AddInternalQueue (Ptr queue) { NS_LOG_FUNCTION (this); + // set various callbacks on the internal queue, so that the queue disc is // notified of packets enqueued, dequeued or dropped by the internal queue queue->TraceConnectWithoutContext ("Enqueue", @@ -327,9 +494,11 @@ QueueDisc::AddInternalQueue (Ptr queue) queue->TraceConnectWithoutContext ("Dequeue", MakeCallback (&QueueDisc::PacketDequeued, this)); queue->TraceConnectWithoutContext ("DropBeforeEnqueue", - MakeCallback (&QueueDisc::DropBeforeEnqueue, this)); + MakeCallback (&InternalQueueDropFunctor::operator(), + &m_internalQueueDbeFunctor)); queue->TraceConnectWithoutContext ("DropAfterDequeue", - MakeCallback (&QueueDisc::DropAfterDequeue, this)); + MakeCallback (&InternalQueueDropFunctor::operator(), + &m_internalQueueDadFunctor)); m_queues.push_back (queue); } @@ -375,6 +544,7 @@ QueueDisc::AddQueueDiscClass (Ptr qdClass) // such queue discs do not implement the enqueue/dequeue methods NS_ABORT_MSG_IF (qdClass->GetQueueDisc ()->GetWakeMode () == WAKE_CHILD, "A queue disc with WAKE_CHILD as wake mode can only be a root queue disc"); + // set the parent callbacks on the child queue disc, so that it can notify // the parent queue disc of packets enqueued, dequeued or dropped qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Enqueue", @@ -382,9 +552,11 @@ QueueDisc::AddQueueDiscClass (Ptr qdClass) qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Dequeue", MakeCallback (&QueueDisc::PacketDequeued, this)); qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropBeforeEnqueue", - MakeCallback (&QueueDisc::DropBeforeEnqueue, this)); + MakeCallback (&ChildQueueDiscDropFunctor::operator(), + &m_childQueueDiscDbeFunctor)); qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropAfterDequeue", - MakeCallback (&QueueDisc::DropAfterDequeue, this)); + MakeCallback (&ChildQueueDiscDropFunctor::operator(), + &m_childQueueDiscDadFunctor)); m_classes.push_back (qdClass); } @@ -448,33 +620,124 @@ QueueDisc::PacketDequeued (Ptr item) } void -QueueDisc::DropBeforeEnqueue (Ptr item) +QueueDisc::DropBeforeEnqueue (Ptr item, const char* reason) { - NS_LOG_FUNCTION (this << item); + NS_LOG_FUNCTION (this << item << reason); m_stats.nTotalDroppedPackets++; m_stats.nTotalDroppedBytes += item->GetSize (); m_stats.nTotalDroppedPacketsBeforeEnqueue++; m_stats.nTotalDroppedBytesBeforeEnqueue += item->GetSize (); + // update the number of packets dropped for the given reason + std::map::iterator itp = m_stats.nDroppedPacketsBeforeEnqueue.find (reason); + if (itp != m_stats.nDroppedPacketsBeforeEnqueue.end ()) + { + itp->second++; + } + else + { + m_stats.nDroppedPacketsBeforeEnqueue[reason] = 1; + } + // update the amount of bytes dropped for the given reason + std::map::iterator itb = m_stats.nDroppedBytesBeforeEnqueue.find (reason); + if (itb != m_stats.nDroppedBytesBeforeEnqueue.end ()) + { + itb->second += item->GetSize (); + } + else + { + m_stats.nDroppedBytesBeforeEnqueue[reason] = item->GetSize (); + } + + NS_LOG_DEBUG ("Total packets/bytes dropped before enqueue: " + << m_stats.nTotalDroppedPacketsBeforeEnqueue << " / " + << m_stats.nTotalDroppedBytesBeforeEnqueue); NS_LOG_LOGIC ("m_traceDropBeforeEnqueue (p)"); m_traceDrop (item); - m_traceDropBeforeEnqueue (item); + m_traceDropBeforeEnqueue (item, reason); } void -QueueDisc::DropAfterDequeue (Ptr item) +QueueDisc::DropAfterDequeue (Ptr item, const char* reason) { - NS_LOG_FUNCTION (this << item); + NS_LOG_FUNCTION (this << item << reason); m_stats.nTotalDroppedPackets++; m_stats.nTotalDroppedBytes += item->GetSize (); m_stats.nTotalDroppedPacketsAfterDequeue++; m_stats.nTotalDroppedBytesAfterDequeue += item->GetSize (); + // update the number of packets dropped for the given reason + std::map::iterator itp = m_stats.nDroppedPacketsAfterDequeue.find (reason); + if (itp != m_stats.nDroppedPacketsAfterDequeue.end ()) + { + itp->second++; + } + else + { + m_stats.nDroppedPacketsAfterDequeue[reason] = 1; + } + // update the amount of bytes dropped for the given reason + std::map::iterator itb = m_stats.nDroppedBytesAfterDequeue.find (reason); + if (itb != m_stats.nDroppedBytesAfterDequeue.end ()) + { + itb->second += item->GetSize (); + } + else + { + m_stats.nDroppedBytesAfterDequeue[reason] = item->GetSize (); + } + + NS_LOG_DEBUG ("Total packets/bytes dropped after dequeue: " + << m_stats.nTotalDroppedPacketsAfterDequeue << " / " + << m_stats.nTotalDroppedBytesAfterDequeue); NS_LOG_LOGIC ("m_traceDropAfterDequeue (p)"); m_traceDrop (item); - m_traceDropAfterDequeue (item); + m_traceDropAfterDequeue (item, reason); +} + +bool +QueueDisc::Mark (Ptr item, const char* reason) +{ + NS_LOG_FUNCTION (this << item << reason); + + bool retval = item->Mark (); + + if (!retval) + { + return false; + } + + m_stats.nTotalMarkedPackets++; + m_stats.nTotalMarkedBytes += item->GetSize (); + + // update the number of packets marked for the given reason + std::map::iterator itp = m_stats.nMarkedPackets.find (reason); + if (itp != m_stats.nMarkedPackets.end ()) + { + itp->second++; + } + else + { + m_stats.nMarkedPackets[reason] = 1; + } + // update the amount of bytes marked for the given reason + std::map::iterator itb = m_stats.nMarkedBytes.find (reason); + if (itb != m_stats.nMarkedBytes.end ()) + { + itb->second += item->GetSize (); + } + else + { + m_stats.nMarkedBytes[reason] = item->GetSize (); + } + + NS_LOG_DEBUG ("Total packets/bytes marked: " + << m_stats.nTotalMarkedPackets << " / " + << m_stats.nTotalMarkedBytes); + m_traceMark (item, reason); + return true; } bool diff --git a/src/traffic-control/model/queue-disc.h b/src/traffic-control/model/queue-disc.h index 7763f891a..4aad70b30 100644 --- a/src/traffic-control/model/queue-disc.h +++ b/src/traffic-control/model/queue-disc.h @@ -25,6 +25,9 @@ #include "ns3/net-device.h" #include "ns3/queue-item.h" #include +#include +#include +#include #include "packet-filter.h" namespace ns3 { @@ -129,6 +132,12 @@ private: * - queued = enqueued - dequeued * - sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet) * + * Separate counters are also kept for each possible reason to drop a packet. + * When a packet is dropped by an internal queue, e.g., because the queue is full, + * the reason is "Dropped by internal queue". When a packet is dropped by a child + * queue disc, the reason is "(Dropped by child queue disc) " followed by the + * reason why the child queue disc dropped the packet. + * * The QueueDisc base class provides the SojournTime trace source, which provides * the sojourn time of every packet dequeued from a queue disc, including packets * that are dropped or requeued after being dequeued. The sojourn time is taken @@ -165,22 +174,62 @@ public: uint32_t nTotalDroppedPackets; /// Total packets dropped before enqueue uint32_t nTotalDroppedPacketsBeforeEnqueue; + /// Packets dropped before enqueue, for each reason + std::map nDroppedPacketsBeforeEnqueue; /// Total packets dropped after dequeue uint32_t nTotalDroppedPacketsAfterDequeue; + /// Packets dropped after dequeue, for each reason + std::map nDroppedPacketsAfterDequeue; /// Total dropped bytes uint64_t nTotalDroppedBytes; /// Total bytes dropped before enqueue uint64_t nTotalDroppedBytesBeforeEnqueue; + /// Bytes dropped before enqueue, for each reason + std::map nDroppedBytesBeforeEnqueue; /// Total bytes dropped after dequeue uint64_t nTotalDroppedBytesAfterDequeue; + /// Bytes dropped after dequeue, for each reason + std::map nDroppedBytesAfterDequeue; /// Total requeued packets uint32_t nTotalRequeuedPackets; /// Total requeued bytes uint64_t nTotalRequeuedBytes; + /// Total marked packets + uint32_t nTotalMarkedPackets; + /// Marked packets, for each reason + std::map nMarkedPackets; + /// Total marked bytes + uint32_t nTotalMarkedBytes; + /// Marked bytes, for each reason + std::map nMarkedBytes; /// constructor Stats (); + /** + * \brief Get the number of packets dropped for the given reason + * \param reason the reason why packets were dropped + * \return the number of packets dropped for the given reason + */ + uint32_t GetNDroppedPackets (std::string reason) const; + /** + * \brief Get the amount of bytes dropped for the given reason + * \param reason the reason why packets were dropped + * \return the amount of bytes dropped for the given reason + */ + uint64_t GetNDroppedBytes (std::string reason) const; + /** + * \brief Get the number of packets marked for the given reason + * \param reason the reason why packets were marked + * \return the number of packets marked for the given reason + */ + uint32_t GetNMarkedPackets (std::string reason) const; + /** + * \brief Get the amount of bytes marked for the given reason + * \param reason the reason why packets were marked + * \return the amount of bytes marked for the given reason + */ + uint64_t GetNMarkedBytes (std::string reason) const; /** * \brief Print the statistics. * \param os output stream in which the data should be printed. @@ -369,6 +418,10 @@ public: */ virtual WakeMode GetWakeMode (void) const; + // Reasons for dropping packets + static constexpr const char* INTERNAL_QUEUE_DROP = "Dropped by internal queue"; //!< Packet dropped by an internal queue + static constexpr const char* CHILD_QUEUE_DISC_DROP = "(Dropped by child queue disc) "; //!< Packet dropped by a child queue disc + protected: /** * \brief Dispose of the object @@ -388,19 +441,30 @@ protected: * \brief Perform the actions required when the queue disc is notified of * a packet dropped before enqueue * \param item item that was dropped - * This method must be called by subclasses to notify parent (this class) of a packet - * dropped before enqueue + * \param reason the reason why the item was dropped + * This method must be called by subclasses to record that a packet was + * dropped before enqueue for the specified reason */ - void DropBeforeEnqueue (Ptr item); + void DropBeforeEnqueue (Ptr item, const char* reason); /** * \brief Perform the actions required when the queue disc is notified of * a packet dropped after dequeue * \param item item that was dropped - * This method must be called by subclasses to notify parent (this class) of a packet - * dropped after dequeue + * \param reason the reason why the item was dropped + * This method must be called by subclasses to record that a packet was + * dropped after dequeue for the specified reason */ - void DropAfterDequeue (Ptr item); + void DropAfterDequeue (Ptr item, const char* reason); + + /** + * \brief Marks the given packet and, if successful, updates the counters + * associated with the given reason + * \param item item that has to be marked + * \param reason the reason why the item has to be marked + * \return true if the item was successfully marked, false otherwise + */ + bool Mark (Ptr item, const char* reason); private: /** @@ -523,19 +587,36 @@ private: Ptr m_devQueueIface; //!< NetDevice queue interface bool m_running; //!< The queue disc is performing multiple dequeue operations Ptr m_requeued; //!< The last packet that failed to be transmitted + std::string m_childQueueDiscDropMsg; //!< Reason why a packet was dropped by a child queue disc /// Traced callback: fired when a packet is enqueued TracedCallback > m_traceEnqueue; - /// Traced callback: fired when a packet is dequeued + /// Traced callback: fired when a packet is dequeued TracedCallback > m_traceDequeue; /// Traced callback: fired when a packet is requeued TracedCallback > m_traceRequeue; /// Traced callback: fired when a packet is dropped TracedCallback > m_traceDrop; /// Traced callback: fired when a packet is dropped before enqueue - TracedCallback > m_traceDropBeforeEnqueue; + TracedCallback, const char* > m_traceDropBeforeEnqueue; /// Traced callback: fired when a packet is dropped after dequeue - TracedCallback > m_traceDropAfterDequeue; + TracedCallback, const char* > m_traceDropAfterDequeue; + /// Traced callback: fired when a packet is marked + TracedCallback, const char* > m_traceMark; + + /// Type for the function objects notifying that a packet has been dropped by an internal queue + typedef std::function)> InternalQueueDropFunctor; + /// Type for the function objects notifying that a packet has been dropped by a child queue disc + typedef std::function, const char*)> ChildQueueDiscDropFunctor; + + /// Function object called when an internal queue dropped a packet before enqueue + InternalQueueDropFunctor m_internalQueueDbeFunctor; + /// Function object called when an internal queue dropped a packet after dequeue + InternalQueueDropFunctor m_internalQueueDadFunctor; + /// Function object called when a child queue disc dropped a packet before enqueue + ChildQueueDiscDropFunctor m_childQueueDiscDbeFunctor; + /// Function object called when a child queue disc dropped a packet after dequeue + ChildQueueDiscDropFunctor m_childQueueDiscDadFunctor; }; /** diff --git a/src/traffic-control/model/red-queue-disc.cc b/src/traffic-control/model/red-queue-disc.cc index c31a7f4d8..abfb4ddf1 100644 --- a/src/traffic-control/model/red-queue-disc.cc +++ b/src/traffic-control/model/red-queue-disc.cc @@ -355,13 +355,6 @@ RedQueueDisc::SetTh (double minTh, double maxTh) m_maxTh = maxTh; } -RedQueueDisc::Stats -RedQueueDisc::GetStats () -{ - NS_LOG_FUNCTION (this); - return m_stats; -} - int64_t RedQueueDisc::AssignStreams (int64_t stream) { @@ -453,23 +446,20 @@ RedQueueDisc::DoEnqueue (Ptr item) if (dropType == DTYPE_UNFORCED) { - if (!m_useEcn || !item->Mark ()) + if (!m_useEcn || !Mark (item, UNFORCED_MARK)) { NS_LOG_DEBUG ("\t Dropping due to Prob Mark " << m_qAvg); - m_stats.unforcedDrop++; - DropBeforeEnqueue (item); + DropBeforeEnqueue (item, UNFORCED_DROP); return false; } NS_LOG_DEBUG ("\t Marking due to Prob Mark " << m_qAvg); - m_stats.unforcedMark++; } else if (dropType == DTYPE_FORCED) { - if (m_useHardDrop || !m_useEcn || !item->Mark ()) + if (m_useHardDrop || !m_useEcn || !Mark (item, FORCED_MARK)) { NS_LOG_DEBUG ("\t Dropping due to Hard Mark " << m_qAvg); - m_stats.forcedDrop++; - DropBeforeEnqueue (item); + DropBeforeEnqueue (item, FORCED_DROP); if (m_isNs1Compat) { m_count = 0; @@ -478,16 +468,10 @@ RedQueueDisc::DoEnqueue (Ptr item) return false; } NS_LOG_DEBUG ("\t Marking due to Hard Mark " << m_qAvg); - m_stats.forcedMark++; } bool retval = GetInternalQueue (0)->Enqueue (item); - if (!retval) - { - m_stats.qLimDrop++; - } - // If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the // internal queue because QueueDisc::AddInternalQueue sets the trace callback @@ -550,11 +534,6 @@ RedQueueDisc::InitializeParams (void) } NS_ASSERT (m_minTh <= m_maxTh); - m_stats.forcedDrop = 0; - m_stats.unforcedDrop = 0; - m_stats.qLimDrop = 0; - m_stats.forcedMark = 0; - m_stats.unforcedMark = 0; m_qAvg = 0.0; m_count = 0; diff --git a/src/traffic-control/model/red-queue-disc.h b/src/traffic-control/model/red-queue-disc.h index 26ecd6235..73f844b0d 100644 --- a/src/traffic-control/model/red-queue-disc.h +++ b/src/traffic-control/model/red-queue-disc.h @@ -108,18 +108,6 @@ public: Below, //!< When m_qAvg < m_minTh }; - /** - * \brief Stats - */ - typedef struct - { - uint32_t unforcedDrop; //!< Early probability drops - uint32_t forcedDrop; //!< Forced drops, m_qAvg > m_maxTh - uint32_t qLimDrop; //!< Drops due to queue limits - uint32_t unforcedMark; //!< Early probability marks - uint32_t forcedMark; //!< Forced marks, m_qAvg > m_maxTh - } Stats; - /** * \brief Drop types */ @@ -232,13 +220,6 @@ public: */ void SetTh (double minTh, double maxTh); - /** - * \brief Get the RED statistics after running. - * - * \returns The drop statistics. - */ - Stats GetStats (); - /** * Assign a fixed random variable stream number to the random variables * used by this model. Return the number of streams (possibly zero) that @@ -249,6 +230,13 @@ public: */ int64_t AssignStreams (int64_t stream); + // Reasons for dropping packets + static constexpr const char* UNFORCED_DROP = "Unforced drop"; //!< Early probability drops + static constexpr const char* FORCED_DROP = "Forced drop"; //!< Forced drops, m_qAvg > m_maxTh + // Reasons for marking packets + static constexpr const char* UNFORCED_MARK = "Unforced mark"; //!< Early probability marks + static constexpr const char* FORCED_MARK = "Forced mark"; //!< Forced marks, m_qAvg > m_maxTh + protected: /** * \brief Dispose of the object @@ -309,8 +297,6 @@ private: */ double ModifyP (double p, uint32_t size); - Stats m_stats; //!< RED statistics - // ** Variables supplied by user QueueDiscMode m_mode; //!< Mode (Bytes or packets) uint32_t m_meanPktSize; //!< Avg pkt size diff --git a/src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc b/src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc index 2dc171b2b..d43934391 100644 --- a/src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc +++ b/src/traffic-control/test/adaptive-red-queue-disc-test-suite.cc @@ -163,8 +163,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute QW"); queue->Initialize (); Enqueue (queue, pktSize, 300); - RedQueueDisc::Stats st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops"); + QueueDisc::Stats st = queue->GetStats (); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be zero unforced drops"); // test 2: Verify automatic setting of QW. [QW = 0.0 with lesser LinkBandwidth] @@ -183,8 +184,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute LinkBandwidth"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); + st = queue->GetStats (); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); // test 3: Verify automatic setting of QW. [QW = -1.0 with default LinkBandwidth] @@ -201,8 +203,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute QW"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops"); + st = queue->GetStats (); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be zero unforced drops"); // test 4: Verify automatic setting of QW. [QW = -1.0 with lesser LinkBandwidth] @@ -221,8 +224,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute LinkBandwidth"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); + st = queue->GetStats (); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); // test 5: Verify automatic setting of QW. [QW = -2.0 with default LinkBandwidth] @@ -239,8 +243,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute QW"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - uint32_t test5 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test5 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_NE (test5, 0, "There should be some unforced drops"); @@ -260,8 +264,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute LinkBandwidth"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - uint32_t test6 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test6 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_NE (test6, test5, "Test 6 should have more unforced drops than Test 5"); @@ -277,8 +281,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute QueueLimit"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); + st = queue->GetStats (); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); // test 8: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with higher LinkBandwidth] @@ -295,8 +300,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) "Verify that we can actually set the attribute LinkBandwidth"); queue->Initialize (); Enqueue (queue, pktSize, 300); - st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops"); + st = queue->GetStats (); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be zero unforced drops"); // test 9: Default RED (automatic and adaptive settings disabled) @@ -319,9 +325,10 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) EnqueueWithDelay (queue, pktSize, 300); Simulator::Stop (Seconds (5)); Simulator::Run (); - st = StaticCast (queue)->GetStats (); - uint32_t test9 = st.unforcedDrop; - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); + st = queue->GetStats (); + uint32_t test9 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); // test 10: Adaptive RED (automatic and adaptive settings enabled) @@ -338,8 +345,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode) EnqueueWithDelay (queue, pktSize, 300); Simulator::Stop (Seconds (5)); Simulator::Run (); - st = StaticCast (queue)->GetStats (); - uint32_t test10 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test10 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_LT (test10, test9, "Test 10 should have less unforced drops than test 9"); } diff --git a/src/traffic-control/test/codel-queue-disc-test-suite.cc b/src/traffic-control/test/codel-queue-disc-test-suite.cc index 2b1099533..774b14005 100644 --- a/src/traffic-control/test/codel-queue-disc-test-suite.cc +++ b/src/traffic-control/test/codel-queue-disc-test-suite.cc @@ -211,7 +211,8 @@ CoDelQueueDiscBasicEnqueueDequeue::DoRun (void) queue->Enqueue (Create (p6, dest, 0)); QueueTestSize (queue, 6 * modeSize, "There should be six packets in queue"); - NS_TEST_EXPECT_MSG_EQ (queue->GetDropOverLimit (), 0, "There should be no packets being dropped due to full queue"); + NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::OVERLIMIT_DROP), + 0, "There should be no packets being dropped due to full queue"); Ptr item; @@ -248,7 +249,8 @@ CoDelQueueDiscBasicEnqueueDequeue::DoRun (void) item = queue->Dequeue (); NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in queue"); - NS_TEST_EXPECT_MSG_EQ (queue->GetDropCount (), 0, "There should be no packet drops according to CoDel algorithm"); + NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP), 0, + "There should be no packet drops according to CoDel algorithm"); } /** @@ -346,7 +348,8 @@ CoDelQueueDiscBasicOverflow::DoRun (void) queue->Enqueue (Create (p3, dest, 0)); QueueTestSize (queue, 500 * modeSize, "There should be 500 packets in queue"); - NS_TEST_EXPECT_MSG_EQ (queue->GetDropOverLimit (), 3, "There should be three packets being dropped due to full queue"); + NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::OVERLIMIT_DROP), + 3, "There should be three packets being dropped due to full queue"); } void @@ -590,7 +593,7 @@ CoDelQueueDiscBasicDrop::Enqueue (Ptr queue, uint32_t size, uint void CoDelQueueDiscBasicDrop::Dequeue (Ptr queue, uint32_t modeSize) { - uint32_t initialDropCount = queue->GetDropCount (); + uint32_t initialDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP); uint32_t initialQSize = queue->GetQueueSize (); uint32_t initialDropNext = queue->GetDropNext (); Time currentTime = Simulator::Now (); @@ -608,7 +611,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr queue, uint32_t modeSize) { if (currentTime < queue->GetInterval ()) { - currentDropCount = queue->GetDropCount (); + currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP); NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "We are not in dropping state." "Sojourn time has just gone above target from below." "Hence, there should be no packet drops"); @@ -617,7 +620,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr queue, uint32_t modeSize) } else if (currentTime >= queue->GetInterval ()) { - currentDropCount = queue->GetDropCount (); + currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP); QueueTestSize (queue, initialQSize - 2 * modeSize, "Sojourn time has been above target for at least interval." "We enter the dropping state, perform initial packet drop, and dequeue the next." "So there should be 2 more packets dequeued."); @@ -628,7 +631,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr queue, uint32_t modeSize) { // In dropping state if (currentTime.GetMicroSeconds () < initialDropNext) { - currentDropCount = queue->GetDropCount (); + currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP); QueueTestSize (queue, initialQSize - modeSize, "We are in dropping state." "Sojourn is still above target." "However, it's not time for next drop." @@ -638,7 +641,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr queue, uint32_t modeSize) } else if (currentTime.GetMicroSeconds () >= initialDropNext) { - currentDropCount = queue->GetDropCount (); + currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP); QueueTestSize (queue, initialQSize - (m_dropNextCount + 1) * modeSize, "We are in dropping state." "It's time for next drop." "The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue"); diff --git a/src/traffic-control/test/pie-queue-disc-test-suite.cc b/src/traffic-control/test/pie-queue-disc-test-suite.cc index 947c1ec34..053e93137 100644 --- a/src/traffic-control/test/pie-queue-disc-test-suite.cc +++ b/src/traffic-control/test/pie-queue-disc-test-suite.cc @@ -245,10 +245,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode) DequeueWithDelay (queue, 0.012, 400); Simulator::Stop (Seconds (8.0)); Simulator::Run (); - PieQueueDisc::Stats st = StaticCast (queue)->GetStats (); - uint32_t test2 = st.unforcedDrop; + QueueDisc::Stats st = queue->GetStats (); + uint32_t test2 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_NE (test2, 0, "There should be some unforced drops"); - NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); // test 3: same as test 2, but with higher QueueDelayReference @@ -276,10 +276,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode) DequeueWithDelay (queue, 0.012, 400); Simulator::Stop (Seconds (8.0)); Simulator::Run (); - st = StaticCast (queue)->GetStats (); - uint32_t test3 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test3 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_LT (test3, test2, "Test 3 should have less unforced drops than test 2"); - NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); // test 4: same as test 2, but with reduced dequeue rate @@ -307,10 +307,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode) DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased Simulator::Stop (Seconds (8.0)); Simulator::Run (); - st = StaticCast (queue)->GetStats (); - uint32_t test4 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test4 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_GT (test4, test2, "Test 4 should have more unforced drops than test 2"); - NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); // test 5: same dequeue rate as test 4, but with higher Tupdate @@ -338,10 +338,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode) DequeueWithDelay (queue, 0.015, 400); Simulator::Stop (Seconds (8.0)); Simulator::Run (); - st = StaticCast (queue)->GetStats (); - uint32_t test5 = st.unforcedDrop; + st = queue->GetStats (); + uint32_t test5 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_LT (test5, test4, "Test 5 should have less unforced drops than test 4"); - NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); } void diff --git a/src/traffic-control/test/red-queue-disc-test-suite.cc b/src/traffic-control/test/red-queue-disc-test-suite.cc index 8f15ab136..09beb90b7 100644 --- a/src/traffic-control/test/red-queue-disc-test-suite.cc +++ b/src/traffic-control/test/red-queue-disc-test-suite.cc @@ -225,10 +225,13 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute QueueLimit"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - RedQueueDisc::Stats st = StaticCast (queue)->GetStats (); - NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should zero dropped packets due probability mark"); - NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should zero dropped packets due hardmark mark"); - NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should zero dropped packets due queue full"); + QueueDisc::Stats st = queue->GetStats (); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be zero unforced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP), 0, + "There should be zero forced dropps"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP), 0, + "There should be zero drops due to queue limit"); // save number of drops from tests struct d { @@ -257,8 +260,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute QW"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test3 = st.unforcedDrop + st.forcedDrop + st.qLimDrop; + st = queue->GetStats (); + drop.test3 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) + + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP) + + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP); NS_TEST_EXPECT_MSG_NE (drop.test3, 0, "There should be some dropped packets"); @@ -277,8 +282,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute QW"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test4 = st.unforcedDrop + st.forcedDrop + st.qLimDrop; + st = queue->GetStats (); + drop.test4 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) + + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP) + + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP); NS_TEST_EXPECT_MSG_GT (drop.test4, drop.test3, "Test 4 should have more drops than test 3"); @@ -299,8 +306,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute LInterm"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test5 = st.unforcedDrop + st.forcedDrop + st.qLimDrop; + st = queue->GetStats (); + drop.test5 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) + + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP) + + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP); NS_TEST_EXPECT_MSG_GT (drop.test5, drop.test3, "Test 5 should have more drops than test 3"); @@ -320,8 +329,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute Gentle"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test6 = st.unforcedDrop + st.forcedDrop + st.qLimDrop; + st = queue->GetStats (); + drop.test6 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) + + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP) + + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP); NS_TEST_EXPECT_MSG_GT (drop.test6, drop.test3, "Test 6 should have more drops than test 3"); @@ -341,8 +352,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute Wait"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test7 = st.unforcedDrop + st.forcedDrop + st.qLimDrop; + st = queue->GetStats (); + drop.test7 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) + + st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP) + + st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP); NS_TEST_EXPECT_MSG_GT (drop.test7, drop.test3, "Test 7 should have more drops than test 3"); @@ -368,10 +381,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute UseECN"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); + st = queue->GetStats (); // Packets are not ECN capable, so there should be only unforced drops, no unforced marks - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); - NS_TEST_EXPECT_MSG_EQ (st.unforcedMark, 0, "There should be no unforced marks"); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0, + "There should be no unforced marks"); // test 9: Packets are ECN capable, but RED queue disc is not ECN enabled @@ -394,10 +409,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute UseECN"); queue->Initialize (); Enqueue (queue, pktSize, 300, true); - st = StaticCast (queue)->GetStats (); + st = queue->GetStats (); // RED queue disc is not ECN enabled, so there should be only unforced drops, no unforced marks - NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops"); - NS_TEST_EXPECT_MSG_EQ (st.unforcedMark, 0, "There should be no unforced marks"); + NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be some unforced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0, + "There should be no unforced marks"); // test 10: Packets are ECN capable and RED queue disc is ECN enabled @@ -420,10 +437,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute UseECN"); queue->Initialize (); Enqueue (queue, pktSize, 300, true); - st = StaticCast (queue)->GetStats (); + st = queue->GetStats (); // Packets are ECN capable, RED queue disc is ECN enabled; there should be only unforced marks, no unforced drops - NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be no unforced drops"); - NS_TEST_EXPECT_MSG_NE (st.unforcedMark, 0, "There should be some unforced marks"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0, + "There should be no unforced drops"); + NS_TEST_EXPECT_MSG_NE (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0, + "There should be some unforced marks"); // test 11: RED with default parameter settings, linear drop probability and fixed m_curMaxP @@ -446,8 +465,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute Gentle"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test11 = st.unforcedDrop; + st = queue->GetStats (); + drop.test11 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_NE (drop.test11, 0, "There should some dropped packets due to probability mark"); @@ -471,8 +490,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute FengAdaptive"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test12 = st.unforcedDrop; + st = queue->GetStats (); + drop.test12 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_LT (drop.test12, drop.test11, "Test 12 should have less drops due to probability mark than test 11"); @@ -498,8 +517,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode) "Verify that we can actually set the attribute NLRED"); queue->Initialize (); Enqueue (queue, pktSize, 300, false); - st = StaticCast (queue)->GetStats (); - drop.test13 = st.unforcedDrop; + st = queue->GetStats (); + drop.test13 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP); NS_TEST_EXPECT_MSG_LT (drop.test13, drop.test11, "Test 13 should have less drops due to probability mark than test 11"); }