diff --git a/src/traffic-control/doc/pie.rst b/src/traffic-control/doc/pie.rst index 9492bcd43..6545b6890 100644 --- a/src/traffic-control/doc/pie.rst +++ b/src/traffic-control/doc/pie.rst @@ -29,7 +29,7 @@ and Takashi Hayakawa. * ``PieQueueDisc::CalculateP ()``: This routine is called at a regular interval of `m_tUpdate` and updates the drop probability, which is required by ``PieQueueDisc::DropEarly()`` - * ``PieQueueDisc::DoDequeue ()``: This routine calculates the average departure rate which is required for updating the drop probability in ``PieQueueDisc::CalculateP ()`` + * ``PieQueueDisc::DoDequeue ()``: This routine calulates `m_qDelay` using timestamp by default or optionally with `UseDqRateEstimator` enabled calculates the average departure rate which is required for updating the drop probability in ``PieQueueDisc::CalculateP ()`` References ========== @@ -56,7 +56,7 @@ The key attributes that the PieQueue class holds include the following: * ``MaxBurstAllowance:`` Current max burst allowance in seconds before random drop. The default value is 0.1 seconds. * ``A:`` Value of alpha. The default value is 0.125. * ``B:`` Value of beta. The default value is 1.25. - +* ``UseDequeueRateEstimator:`` Enable/Disable usage of Dequeue Rate Estimator (Default: false). Examples ======== @@ -80,6 +80,7 @@ The PIE model is tested using :cpp:class:`PieQueueDiscTestSuite` class defined i * Test 3: same as test 2, but with higher QueueDelayReference * Test 4: same as test 2, but with reduced dequeue rate * Test 5: same dequeue rate as test 4, but with higher Tupdate +* Test 6: same as test 2, but with UseDequeueRateEstimator enabled The test suite can be run using the following commands: diff --git a/src/traffic-control/model/pie-queue-disc.cc b/src/traffic-control/model/pie-queue-disc.cc index 02f55179e..2e5805297 100644 --- a/src/traffic-control/model/pie-queue-disc.cc +++ b/src/traffic-control/model/pie-queue-disc.cc @@ -92,6 +92,11 @@ TypeId PieQueueDisc::GetTypeId (void) TimeValue (Seconds (0.1)), MakeTimeAccessor (&PieQueueDisc::m_maxBurst), MakeTimeChecker ()) + .AddAttribute ("UseDequeueRateEstimator", + "Enable/Disable usage of Dequeue Rate Estimator", + BooleanValue (false), + MakeBooleanAccessor (&PieQueueDisc::m_useDqRateEstimator), + MakeBooleanChecker ()) ; return tid; @@ -122,7 +127,6 @@ PieQueueDisc::DoDispose (void) Time PieQueueDisc::GetQueueDelay (void) { - NS_LOG_FUNCTION (this); return m_qDelay; } @@ -236,17 +240,25 @@ void PieQueueDisc::CalculateP () Time qDelay; double p = 0.0; bool missingInitFlag = false; - if (m_avgDqRate > 0) + + if (m_useDqRateEstimator) { - qDelay = Time (Seconds (GetInternalQueue (0)->GetNBytes () / m_avgDqRate)); + if (m_avgDqRate > 0) + { + qDelay = Time (Seconds (GetInternalQueue (0)->GetNBytes () / m_avgDqRate)); + } + else + { + qDelay = Time (Seconds (0)); + missingInitFlag = true; + } + m_qDelay = qDelay; } else { - qDelay = Time (Seconds (0)); - missingInitFlag = true; + qDelay = m_qDelay; } - - m_qDelay = qDelay; + NS_LOG_DEBUG ("Queue delay while calculating probability: " << qDelay.GetMilliSeconds () << "ms"); if (m_burstAllowance.GetSeconds () > 0) { @@ -357,51 +369,62 @@ PieQueueDisc::DoDequeue () // if not in a measurement cycle and the queue has built up to dq_threshold, // start the measurement cycle - - if ( (GetInternalQueue (0)->GetNBytes () >= m_dqThreshold) && (!m_inMeasurement) ) + if (m_useDqRateEstimator) { - m_dqStart = now; - m_dqCount = 0; - m_inMeasurement = true; - } - - if (m_inMeasurement) - { - m_dqCount += pktSize; - - // done with a measurement cycle - if (m_dqCount >= m_dqThreshold) + if ( (GetInternalQueue (0)->GetNBytes () >= m_dqThreshold) && (!m_inMeasurement) ) { + m_dqStart = now; + m_dqCount = 0; + m_inMeasurement = true; + } - double tmp = now - m_dqStart; + if (m_inMeasurement) + { + m_dqCount += pktSize; - if (tmp > 0) + // done with a measurement cycle + if (m_dqCount >= m_dqThreshold) { - if (m_avgDqRate == 0) + + double tmp = now - m_dqStart; + + if (tmp > 0) { - m_avgDqRate = m_dqCount / tmp; + if (m_avgDqRate == 0) + { + m_avgDqRate = m_dqCount / tmp; + } + else + { + m_avgDqRate = (0.5 * m_avgDqRate) + (0.5 * (m_dqCount / tmp)); + } + } + NS_LOG_DEBUG ("Average Dequeue Rate after Dequeue: " << m_avgDqRate); + + // restart a measurement cycle if there is enough data + if (GetInternalQueue (0)->GetNBytes () > m_dqThreshold) + { + m_dqStart = now; + m_dqCount = 0; + m_inMeasurement = true; } else { - m_avgDqRate = (0.5 * m_avgDqRate) + (0.5 * (m_dqCount / tmp)); + m_dqCount = 0; + m_inMeasurement = false; } } - - // restart a measurement cycle if there is enough data - if (GetInternalQueue (0)->GetNBytes () > m_dqThreshold) - { - m_dqStart = now; - m_dqCount = 0; - m_inMeasurement = true; - } - else - { - m_dqCount = 0; - m_inMeasurement = false; - } } } + else + { + m_qDelay = Time (Seconds (now - item->GetTimeStamp ().GetSeconds ())); + if (GetInternalQueue (0)->GetNBytes () == 0) + { + m_qDelay = Time (Seconds (0)); + } + } return item; } diff --git a/src/traffic-control/model/pie-queue-disc.h b/src/traffic-control/model/pie-queue-disc.h index 2439496e9..f5ece7013 100644 --- a/src/traffic-control/model/pie-queue-disc.h +++ b/src/traffic-control/model/pie-queue-disc.h @@ -38,6 +38,7 @@ #define BURST_RESET_TIMEOUT 1.5 +class PieQueueDiscTestCase; // Forward declaration for unit test namespace ns3 { class TraceContainer; @@ -105,6 +106,7 @@ protected: virtual void DoDispose (void); private: + friend class::PieQueueDiscTestCase; // Test code virtual bool DoEnqueue (Ptr item); virtual Ptr DoDequeue (void); virtual bool CheckConfig (void); @@ -140,6 +142,7 @@ private: double m_a; //!< Parameter to pie controller double m_b; //!< Parameter to pie controller uint32_t m_dqThreshold; //!< Minimum queue size in bytes before dequeue rate is measured + bool m_useDqRateEstimator; //!< Enable/Disable usage of dequeue rate estimator for queue delay calculation // ** Variables maintained by PIE double m_dropProb; //!< Variable used in calculation of drop probability 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 f6d62bc36..125b39b53 100644 --- a/src/traffic-control/test/pie-queue-disc-test-suite.cc +++ b/src/traffic-control/test/pie-queue-disc-test-suite.cc @@ -220,14 +220,8 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode) pktSize = 1000; // pktSize != 0 because DequeueThreshold always works in bytes NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))), true, "Verify that we can actually set the attribute MaxSize"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true, - "Verify that we can actually set the attribute A"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true, - "Verify that we can actually set the attribute B"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true, "Verify that we can actually set the attribute Tupdate"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true, - "Verify that we can actually set the attribute Supdate"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true, "Verify that we can actually set the attribute DequeueThreshold"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true, @@ -249,14 +243,8 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode) queue = CreateObject (); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))), true, "Verify that we can actually set the attribute MaxSize"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true, - "Verify that we can actually set the attribute A"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true, - "Verify that we can actually set the attribute B"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true, "Verify that we can actually set the attribute Tupdate"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true, - "Verify that we can actually set the attribute Supdate"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true, "Verify that we can actually set the attribute DequeueThreshold"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.08))), true, @@ -278,14 +266,8 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode) queue = CreateObject (); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))), true, "Verify that we can actually set the attribute MaxSize"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true, - "Verify that we can actually set the attribute A"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true, - "Verify that we can actually set the attribute B"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.03))), true, "Verify that we can actually set the attribute Tupdate"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true, - "Verify that we can actually set the attribute Supdate"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true, "Verify that we can actually set the attribute DequeueThreshold"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true, @@ -307,14 +289,8 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode) queue = CreateObject (); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))), true, "Verify that we can actually set the attribute MaxSize"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("A", DoubleValue (0.125)), true, - "Verify that we can actually set the attribute A"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("B", DoubleValue (1.25)), true, - "Verify that we can actually set the attribute B"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Tupdate", TimeValue (Seconds (0.09))), true, "Verify that we can actually set the attribute Tupdate"); - NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Supdate", TimeValue (Seconds (0.0))), true, - "Verify that we can actually set the attribute Supdate"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("DequeueThreshold", UintegerValue (10000)), true, "Verify that we can actually set the attribute DequeueThreshold"); NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueDelayReference", TimeValue (Seconds (0.02))), true, @@ -330,6 +306,23 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode) 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.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); + + + // test 6: same as test 2, but with UseDequeueRateEstimator enabled + queue = CreateObject (); + NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (mode, qSize))), + true, "Verify that we can actually set the attribute MaxSize"); + NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseDequeueRateEstimator", BooleanValue (true)), true, + "Verify that we can actually set the attribute UseTimestamp"); + queue->Initialize (); + EnqueueWithDelay (queue, pktSize, 400); + DequeueWithDelay (queue, 0.014, 400); + Simulator::Stop (Seconds (8.0)); + Simulator::Run (); + st = queue->GetStats (); + uint32_t test6 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP); + NS_TEST_EXPECT_MSG_NE (test6, 0, "There should be some unforced drops"); + NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops"); } void