traffic-control: Add usage of timestamp for latency calculation for PIE

This commit is contained in:
Bhaskar Kataria
2020-05-04 00:19:49 +05:30
committed by Tom Henderson
parent b99295e119
commit bdb5f393dd
4 changed files with 84 additions and 64 deletions

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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<QueueDiscItem> item);
virtual Ptr<QueueDiscItem> 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

View File

@@ -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<PieQueueDisc> ();
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<PieQueueDisc> ();
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<PieQueueDisc> ();
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<PieQueueDisc> ();
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