diff --git a/CHANGES.html b/CHANGES.html
index 56737ac2247736fdeb5f86444c70d35b971c7d3b..defbb8b08de7432a27c053e052e6a2e2fc6fdb27 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -55,11 +55,13 @@ us a note on ns-developers mailing list.
New API:
- A new TCP congestion control, TcpLinuxReno, has been added.
+- Added queue delay calculation using timestamp feature (Linux default), cap drop adjustment feature (Section 5.5 of RFC 8033), ECN (Section 5.1 of RFC 8033) and Derandomization feature (Section 5.4 of RFC 8033) to PIE queue disc.
Changes to existing API:
- Added "--enable-asserts" and "--enable-logs" to waf configure, to selectively enable asserts and/or logs in release and optimized builds.
- The Sifs, Slot and Pifs attributes have been moved from WifiMac to WifiPhy to better reflect that they are PHY characteristics, to decouple the MAC configuration from the PHY configuration and to ease the support for future standards.
+- PIE queue disc now uses Timestamp for queue delay calculation as default instead of Dequeue Rate Estimator
Changes to build system:
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 8f39c298a9a14c6e7e1f7e96e2c128e4173fb68b..ad04491466f90a1a8e28c9f974bbbce3aaa35c4e 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -17,6 +17,10 @@ New user-visible features
- (build system) Added "--enable-asserts" and "--enable-logs" to waf configure,
to selectively enable asserts and/or logs in release and optimized builds.
- (tcp) Added TcpLinuxReno congestion control (aligns with Linux 'reno' congestion control).
+- (traffic-control) Added queue delay calculation using timestamp feature
+ (Linux default), cap drop adjustment feature (Section 5.5 of RFC 8033), ECN
+ (Section 5.1 of RFC 8033) and Derandomization feature (Section 5.4 of RFC
+ 8033) to PIE queue disc.
Bugs fixed
----------
diff --git a/src/traffic-control/doc/pie.rst b/src/traffic-control/doc/pie.rst
index 9492bcd43747c56af161e9ce6a0221c221e79a63..f40e6a2c8da4549f9c75e0f5f7c64a240aa2656f 100644
--- a/src/traffic-control/doc/pie.rst
+++ b/src/traffic-control/doc/pie.rst
@@ -19,7 +19,10 @@ The source code for the PIE model is located in the directory ``src/traffic-cont
and consists of 2 files `pie-queue-disc.h` and `pie-queue-disc.cc` defining a PieQueueDisc
class. The code was ported to |ns3| by Mohit P. Tahiliani, Shravya K. S. and Smriti Murali
based on ns-2 code implemented by Preethi Natarajan, Rong Pan, Chiara Piglione, Greg White
-and Takashi Hayakawa.
+and Takashi Hayakawa. The implementation was aligned with RFC 8033 by Vivek Jain and Mohit
+P. Tahiliani after ns-3.32 release, and additional unit test cases were added for the same
+by Bhaskar Kataria during his GSoC 2020 project.
+
* class :cpp:class:`PieQueueDisc`: This class implements the main PIE algorithm:
@@ -29,7 +32,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 ()``. From ns-3.32 onwards, the default approach to calculate queue delay has been changed to use timestamps.
References
==========
@@ -56,6 +59,11 @@ 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).
+* ``UseEcn:`` True to use ECN. Packets are marked instead of being dropped (Default: false).
+* ``MarkEcnThreshold:`` ECN marking threshold (Default: 10% as suggested in RFC 8033).
+* ``UseDerandomization:`` Enable/Disable Derandomization feature mentioned in RFC 8033 (Default: false).
+* ``UseCapDropAdjustment:`` Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033 (Default: true).
Examples
========
@@ -80,6 +88,15 @@ 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
+* Test 7: test with CapDropAdjustment disabled
+* Test 8: test with CapDropAdjustment enabled
+* Test 9: PIE queue disc is ECN enabled, but packets are not ECN capable
+* Test 10: Packets are ECN capable, but PIE queue disc is not ECN enabled
+* Test 11: Packets and PIE queue disc both are ECN capable
+* Test 12: test with Derandomization enabled
+* Test 13: same as test 11 but with accumulated drop probability set below the low threshold
+* Test 14: same as test 12 but with accumulated drop probability set above the high threshold
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 02f55179e6182b8f83245e20a1e779a2aff13a48..939b8fac30d7269a3f43e29d4e1bb1c8bfcbe948 100644
--- a/src/traffic-control/model/pie-queue-disc.cc
+++ b/src/traffic-control/model/pie-queue-disc.cc
@@ -63,7 +63,7 @@ TypeId PieQueueDisc::GetTypeId (void)
MakeDoubleChecker ())
.AddAttribute ("Tupdate",
"Time period to calculate drop probability",
- TimeValue (Seconds (0.03)),
+ TimeValue (Seconds (0.015)),
MakeTimeAccessor (&PieQueueDisc::m_tUpdate),
MakeTimeChecker ())
.AddAttribute ("Supdate",
@@ -79,19 +79,44 @@ TypeId PieQueueDisc::GetTypeId (void)
MakeQueueSizeChecker ())
.AddAttribute ("DequeueThreshold",
"Minimum queue size in bytes before dequeue rate is measured",
- UintegerValue (10000),
+ UintegerValue (16384),
MakeUintegerAccessor (&PieQueueDisc::m_dqThreshold),
MakeUintegerChecker ())
.AddAttribute ("QueueDelayReference",
"Desired queue delay",
- TimeValue (Seconds (0.02)),
+ TimeValue (Seconds (0.015)),
MakeTimeAccessor (&PieQueueDisc::m_qDelayRef),
MakeTimeChecker ())
.AddAttribute ("MaxBurstAllowance",
- "Current max burst allowance in seconds before random drop",
- TimeValue (Seconds (0.1)),
+ "Current max burst allowance before random drop",
+ TimeValue (Seconds (0.15)),
MakeTimeAccessor (&PieQueueDisc::m_maxBurst),
MakeTimeChecker ())
+ .AddAttribute ("UseDequeueRateEstimator",
+ "Enable/Disable usage of Dequeue Rate Estimator",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PieQueueDisc::m_useDqRateEstimator),
+ MakeBooleanChecker ())
+ .AddAttribute ("UseCapDropAdjustment",
+ "Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033",
+ BooleanValue (true),
+ MakeBooleanAccessor (&PieQueueDisc::m_isCapDropAdjustment),
+ MakeBooleanChecker ())
+ .AddAttribute ("UseEcn",
+ "True to use ECN (packets are marked instead of being dropped)",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PieQueueDisc::m_useEcn),
+ MakeBooleanChecker ())
+ .AddAttribute ("MarkEcnThreshold",
+ "ECN marking threshold (RFC 8033 suggests 0.1 (i.e., 10%) default)",
+ DoubleValue (0.1),
+ MakeDoubleAccessor (&PieQueueDisc::m_markEcnTh),
+ MakeDoubleChecker (0,1))
+ .AddAttribute ("UseDerandomization",
+ "Enable/Disable Derandomization feature mentioned in RFC 8033",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PieQueueDisc::m_useDerandomization),
+ MakeBooleanChecker ())
;
return tid;
@@ -122,7 +147,6 @@ PieQueueDisc::DoDispose (void)
Time
PieQueueDisc::GetQueueDelay (void)
{
- NS_LOG_FUNCTION (this);
return m_qDelay;
}
@@ -145,13 +169,18 @@ PieQueueDisc::DoEnqueue (Ptr item)
{
// Drops due to queue limit: reactive
DropBeforeEnqueue (item, FORCED_DROP);
+ m_accuProb = 0;
return false;
}
else if (DropEarly (item, nQueued.GetValue ()))
{
- // Early probability drop: proactive
- DropBeforeEnqueue (item, UNFORCED_DROP);
- return false;
+ if (!m_useEcn || m_dropProb >= m_markEcnTh || !Mark (item, UNFORCED_MARK))
+ {
+ // Early probability drop: proactive
+ DropBeforeEnqueue (item, UNFORCED_DROP);
+ m_accuProb = 0;
+ return false;
+ }
}
// No drop
@@ -177,6 +206,7 @@ PieQueueDisc::InitializeParams (void)
m_dqStart = 0;
m_burstState = NO_BURST;
m_qDelayOld = Time (Seconds (0));
+ m_accuProb = 0.0;
}
bool PieQueueDisc::DropEarly (Ptr item, uint32_t qSize)
@@ -202,9 +232,8 @@ bool PieQueueDisc::DropEarly (Ptr item, uint32_t qSize)
{
p = p * packetSize / m_meanPktSize;
}
- bool earlyDrop = true;
- double u = m_uv->GetValue ();
+ // Safeguard PIE to be work conserving (Section 4.1 of RFC 8033)
if ((m_qDelayOld.GetSeconds () < (0.5 * m_qDelayRef.GetSeconds ())) && (m_dropProb < 0.2))
{
return false;
@@ -218,11 +247,25 @@ bool PieQueueDisc::DropEarly (Ptr item, uint32_t qSize)
return false;
}
- if (u > p)
+ if (m_useDerandomization)
{
- earlyDrop = false;
+ if (m_dropProb == 0)
+ {
+ m_accuProb = 0;
+ }
+ m_accuProb += m_dropProb;
+ if (m_accuProb < 0.85)
+ {
+ return false;
+ }
+ else if (m_accuProb >= 8.5)
+ {
+ return true;
+ }
}
- if (!earlyDrop)
+
+ double u = m_uv->GetValue ();
+ if (u > p)
{
return false;
}
@@ -236,17 +279,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)
{
@@ -255,7 +306,19 @@ void PieQueueDisc::CalculateP ()
else
{
p = m_a * (qDelay.GetSeconds () - m_qDelayRef.GetSeconds ()) + m_b * (qDelay.GetSeconds () - m_qDelayOld.GetSeconds ());
- if (m_dropProb < 0.001)
+ if (m_dropProb < 0.000001)
+ {
+ p /= 2048;
+ }
+ else if (m_dropProb < 0.00001)
+ {
+ p /= 512;
+ }
+ else if (m_dropProb < 0.0001)
+ {
+ p /= 128;
+ }
+ else if (m_dropProb < 0.001)
{
p /= 32;
}
@@ -267,19 +330,15 @@ void PieQueueDisc::CalculateP ()
{
p /= 2;
}
- else if (m_dropProb < 1)
- {
- p /= 0.5;
- }
- else if (m_dropProb < 10)
- {
- p /= 0.125;
- }
else
{
- p /= 0.03125;
+ // The pseudocode in Section 4.2 of RFC 8033 suggests to use this for
+ // assignment of p, but this assignment causes build failure on Mac OS
+ // p = p;
}
- if ((m_dropProb >= 0.1) && (p > 0.02))
+
+ // Cap Drop Adjustment (Section 5.5 of RFC 8033)
+ if (m_isCapDropAdjustment && (m_dropProb >= 0.1) && (p > 0.02))
{
p = 0.02;
}
@@ -288,17 +347,27 @@ void PieQueueDisc::CalculateP ()
p += m_dropProb;
// For non-linear drop in prob
-
+ // Decay the drop probability exponentially (Section 4.2 of RFC 8033)
if (qDelay.GetSeconds () == 0 && m_qDelayOld.GetSeconds () == 0)
{
p *= 0.98;
}
- else if (qDelay.GetSeconds () > 0.2)
+
+ // bound the drop probability (Section 4.2 of RFC 8033)
+ if (p < 0)
+ {
+ m_dropProb = 0;
+ }
+ else if (p > 1)
+ {
+ m_dropProb = 1;
+ }
+ else
{
- p += 0.02;
+ m_dropProb = p;
}
- m_dropProb = (p > 0) ? p : 0;
+ // Section 4.4 #2
if (m_burstAllowance < m_tUpdate)
{
m_burstAllowance = Time (Seconds (0));
@@ -357,51 +426,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) )
- {
- m_dqStart = now;
- m_dqCount = 0;
- m_inMeasurement = true;
- }
-
- if (m_inMeasurement)
+ if (m_useDqRateEstimator)
{
- 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)
+ {
+ 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_avgDqRate = m_dqCount / tmp;
+ 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 2439496e91cadff4d503ed3b209db388e137fc6c..ac54bf244c429354c0d5f83012721fb399f19fa9 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;
@@ -83,7 +84,6 @@ public:
* \returns The current queue delay.
*/
Time GetQueueDelay (void);
-
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
@@ -97,6 +97,7 @@ public:
// 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
+ static constexpr const char* UNFORCED_MARK = "Unforced mark"; //!< Early probability marks: proactive
protected:
/**
@@ -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,11 @@ 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
+ bool m_isCapDropAdjustment; //!< Enable/Disable Cap Drop Adjustment feature mentioned in RFC 8033
+ bool m_useEcn; //!< Enable ECN Marking functionality
+ bool m_useDerandomization; //!< Enable Derandomization feature mentioned in RFC 8033
+ double m_markEcnTh; //!< ECN marking threshold (default 10% as suggested in RFC 8033)
// ** Variables maintained by PIE
double m_dropProb; //!< Variable used in calculation of drop probability
@@ -154,6 +161,7 @@ private:
uint64_t m_dqCount; //!< Number of bytes departed since current measurement cycle starts
EventId m_rtrsEvent; //!< Event used to decide the decision of interval of drop probability calculation
Ptr m_uv; //!< Rng stream
+ double m_accuProb; //!< Accumulated drop probability
};
}; // namespace ns3
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 f6d62bc36194e8fb27ad7ddbc0c7c0f0fe284b5b..9aef5b40dd5b4044d35a42919e6e73ff1368ada6 100644
--- a/src/traffic-control/test/pie-queue-disc-test-suite.cc
+++ b/src/traffic-control/test/pie-queue-disc-test-suite.cc
@@ -46,12 +46,31 @@ public:
*
* \param p the packet
* \param addr the address
+ * \param ecnCapable ECN capable flag
*/
- PieQueueDiscTestItem (Ptr p, const Address & addr);
+ PieQueueDiscTestItem (Ptr p, const Address & addr, bool ecnCapable);
virtual ~PieQueueDiscTestItem ();
virtual void AddHeader (void);
virtual bool Mark (void);
+ // ** Variables for testing m_isCapDropAdjustment
+ double m_maxDropProbDiff = 0.0; //!< Maximum difference between two consecutive drop probability values
+ double m_prevDropProb = 0.0; //!< Previous drop probability
+ bool m_checkProb = false; //!< Enable/Disable drop probability checks
+
+ // ** Variable for testing ECN
+ double m_maxDropProb = 0.0; //!< Maximum value of drop probability
+ bool m_ecnCapable = false; //!< Enable/Disable ECN capability
+
+ // ** Variables for testing Derandomization
+ bool m_checkAccuProb = false; //!< Enable/Disable accumulated drop probability checks
+ bool m_constAccuProb = false; //!< Enable/Disable fixed accumulated drop probability
+ bool m_checkMaxAccuProb = false; //!< Enable/Disable Maximum accumulated drop probability checks
+ double m_accuProbError = 0.0; //!< Error in accumulated drop probability
+ double m_prevAccuProb = 0.0; //!< Previous accumulated drop probability
+ double m_setAccuProb = 0.0; //!< Value to be set for accumulated drop probability
+ uint32_t m_expectedDrops = 0; //!< Number of expected unforced drops
+
private:
PieQueueDiscTestItem ();
/**
@@ -65,10 +84,11 @@ private:
* Disable default implementation to avoid misuse
*/
PieQueueDiscTestItem &operator = (const PieQueueDiscTestItem &);
+ bool m_ecnCapablePacket; //!< ECN capable packet?
};
-PieQueueDiscTestItem::PieQueueDiscTestItem (Ptr p, const Address & addr)
- : QueueDiscItem (p, addr, 0)
+PieQueueDiscTestItem::PieQueueDiscTestItem (Ptr p, const Address & addr, bool ecnCapable)
+ : QueueDiscItem (p, addr, 0), m_ecnCapablePacket (ecnCapable)
{
}
@@ -84,6 +104,10 @@ PieQueueDiscTestItem::AddHeader (void)
bool
PieQueueDiscTestItem::Mark (void)
{
+ if (m_ecnCapablePacket)
+ {
+ return true;
+ }
return false;
}
@@ -104,15 +128,17 @@ private:
* \param queue the queue disc
* \param size the size
* \param nPkt the number of packets
+ * \param testAttributes attributes for testing
*/
- void Enqueue (Ptr queue, uint32_t size, uint32_t nPkt);
+ void Enqueue (Ptr queue, uint32_t size, uint32_t nPkt, Ptr testAttributes);
/**
* Enqueue with delay function
* \param queue the queue disc
* \param size the size
* \param nPkt the number of packets
+ * \param testAttributes attributes for testing
*/
- void EnqueueWithDelay (Ptr queue, uint32_t size, uint32_t nPkt);
+ void EnqueueWithDelay (Ptr queue, uint32_t size, uint32_t nPkt, Ptr testAttributes);
/**
* Dequeue function
* \param queue the queue disc
@@ -131,6 +157,24 @@ private:
* \param mode the test mode
*/
void RunPieTest (QueueSizeUnit mode);
+ /**
+ * \brief Check Drop Probability
+ * \param queue the queue disc
+ * \param testAttributes attributes for testing
+ */
+ void CheckDropProb (Ptr queue, Ptr testAttributes);
+ /**
+ * \brief Check Accumulated Drop Probability
+ * \param queue the queue disc
+ * \param testAttributes attributes for testing
+ */
+ void CheckAccuProb (Ptr queue, Ptr testAttributes);
+ /**
+ * \brief Check Maximum Accumulated Drop Probability
+ * \param queue the queue disc
+ * \param testAttributes attributes for testing
+ */
+ void CheckMaxAccuProb (Ptr queue, Ptr testAttributes);
};
PieQueueDiscTestCase::PieQueueDiscTestCase ()
@@ -152,6 +196,8 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
// test 1: simple enqueue/dequeue with defaults, no drops
Address dest;
+ // PieQueueDiscItem pointer for attributes
+ Ptr testAttributes = Create (Create (pktSize), dest, false);
if (mode == QueueSizeUnit::BYTES)
{
@@ -176,16 +222,16 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
queue->Initialize ();
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 0 * modeSize, "There should be no packets in there");
- queue->Enqueue (Create (p1, dest));
+ queue->Enqueue (Create (p1, dest, false));
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 1 * modeSize, "There should be one packet in there");
- queue->Enqueue (Create (p2, dest));
+ queue->Enqueue (Create (p2, dest, false));
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 2 * modeSize, "There should be two packets in there");
- queue->Enqueue (Create (p3, dest));
- queue->Enqueue (Create (p4, dest));
- queue->Enqueue (Create (p5, dest));
- queue->Enqueue (Create (p6, dest));
- queue->Enqueue (Create (p7, dest));
- queue->Enqueue (Create (p8, dest));
+ queue->Enqueue (Create (p3, dest, false));
+ queue->Enqueue (Create (p4, dest, false));
+ queue->Enqueue (Create (p5, dest, false));
+ queue->Enqueue (Create (p6, dest, false));
+ queue->Enqueue (Create (p7, dest, false));
+ queue->Enqueue (Create (p8, dest, false));
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 8 * modeSize, "There should be eight packets in there");
Ptr item;
@@ -217,17 +263,13 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
// test 2: more data with defaults, unforced drops but no forced drops
queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
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,
@@ -235,7 +277,7 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
"Verify that we can actually set the attribute MaxBurstAllowance");
queue->Initialize ();
- EnqueueWithDelay (queue, pktSize, 400);
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
DequeueWithDelay (queue, 0.012, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
@@ -247,16 +289,12 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
// test 3: same as test 2, but with higher QueueDelayReference
queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
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,
@@ -264,7 +302,7 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
"Verify that we can actually set the attribute MaxBurstAllowance");
queue->Initialize ();
- EnqueueWithDelay (queue, pktSize, 400);
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
DequeueWithDelay (queue, 0.012, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
@@ -276,16 +314,12 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
// test 4: same as test 2, but with reduced dequeue rate
queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
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,
@@ -293,7 +327,7 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
"Verify that we can actually set the attribute MaxBurstAllowance");
queue->Initialize ();
- EnqueueWithDelay (queue, pktSize, 400);
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
@@ -305,16 +339,12 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
// test 5: same dequeue rate as test 4, but with higher Tupdate
queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
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,
@@ -322,7 +352,7 @@ PieQueueDiscTestCase::RunPieTest (QueueSizeUnit mode)
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxBurstAllowance", TimeValue (Seconds (0.1))), true,
"Verify that we can actually set the attribute MaxBurstAllowance");
queue->Initialize ();
- EnqueueWithDelay (queue, pktSize, 400);
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
DequeueWithDelay (queue, 0.015, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
@@ -330,26 +360,290 @@ 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 ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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, testAttributes);
+ 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");
+
+
+ // test 7: test with CapDropAdjustment disabled
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseCapDropAdjustment", BooleanValue (false)), true,
+ "Verify that we can actually set the attribute UseCapDropAdjustment");
+ queue->Initialize ();
+ testAttributes->m_checkProb = true;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test7 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
+ NS_TEST_EXPECT_MSG_NE (test7, 0, "There should be some unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+ NS_TEST_EXPECT_MSG_GT (testAttributes->m_maxDropProbDiff, 0.02,
+ "Maximum increase in drop probability should be greater than 0.02");
+
+
+ // test 8: test with CapDropAdjustment enabled
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseCapDropAdjustment", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseCapDropAdjustment");
+ queue->Initialize ();
+ testAttributes->m_checkProb = true;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test8 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
+ NS_TEST_EXPECT_MSG_NE (test8, 0, "There should be some unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+ NS_TEST_EXPECT_MSG_LT (testAttributes->m_maxDropProbDiff, 0.0200000000000001,
+ "Maximum increase in drop probability should be less than or equal to 0.02");
+
+
+ // test 9: PIE queue disc is ECN enabled, but packets are not ECN capable
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseEcn", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseEcn");
+ NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
+ "Verify that we can actually set the attribute MarkEcnThreshold");
+ queue->Initialize ();
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test9 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
+ NS_TEST_EXPECT_MSG_EQ (test9, 0, "There should be zero unforced marks");
+ NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+
+
+ // test 10: Packets are ECN capable, but PIE queue disc is not ECN enabled
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseEcn", BooleanValue (false)), true,
+ "Verify that we can actually set the attribute UseEcn");
+ NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
+ "Verify that we can actually set the attribute MarkEcnThreshold");
+ queue->Initialize ();
+ testAttributes->m_ecnCapable = true;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test10 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
+ NS_TEST_EXPECT_MSG_EQ (test10, 0, "There should be zero unforced marks");
+ NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+
+
+ // test 11: Packets and PIE queue disc both are ECN capable
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseEcn", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseEcn");
+ NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MarkEcnThreshold", DoubleValue (0.3)), true,
+ "Verify that we can actually set the attribute MarkEcnThreshold");
+ queue->Initialize ();
+ testAttributes->m_ecnCapable = true;
+ testAttributes->m_checkProb = true;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test11 = st.GetNMarkedPackets (PieQueueDisc::UNFORCED_MARK);
+ NS_TEST_EXPECT_MSG_NE (test11, 0, "There should be some unforced marks");
+ // There are unforced drops because the value of m_maxDropProb goes beyond 0.3 in this test.
+ // PIE drops the packets even when they are ECN capable if drop probability is more than 30%.
+ NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP), 0, "There should be some unforced drops");
+ // Confirm that m_maxDropProb goes above 0.3 in this test
+ NS_TEST_EXPECT_MSG_GT (testAttributes->m_maxDropProb, 0.3, "Maximum Drop probability should be greater than 0.3");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+
+
+ // test 12: test with derandomization enabled
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseDerandomization", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseDerandomization");
+ queue->Initialize ();
+ testAttributes->m_checkAccuProb = true;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test12 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
+ NS_TEST_EXPECT_MSG_NE (test12, 0, "There should be some unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+ NS_TEST_EXPECT_MSG_EQ (testAttributes->m_accuProbError, 0.0, "There should not be any error in setting accuProb");
+
+
+ // test 13: same as test 11 but with accumulated drop probability set below the low threshold
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("UseDerandomization", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseDerandomization");
+ queue->Initialize ();
+ testAttributes->m_constAccuProb = true;
+ // Final value of accumulated drop probability to drop packet will be maximum 0.84 while threshold to drop packet is 0.85
+ testAttributes->m_setAccuProb = -0.16;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test13 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
+ NS_TEST_EXPECT_MSG_EQ (test13, 0, "There should be zero unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
+
+
+ // test 14: same as test 12 but with accumulated drop probability set above the high threshold
+ queue = CreateObject ();
+ // PieQueueDiscItem pointer for attributes
+ testAttributes = Create (Create (pktSize), dest, false);
+ 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 ("MaxBurstAllowance", TimeValue (Seconds (0.0))), true,
+ "Verify that we can actually set the attribute MaxBurstAllowance");
+ NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("UseDerandomization", BooleanValue (true)), true,
+ "Verify that we can actually set the attribute UseDerandomization");
+ queue->Initialize ();
+ testAttributes->m_constAccuProb = true;
+ testAttributes->m_checkMaxAccuProb = true;
+ // Final value of accumulated drop probability to drop packet will be minimum 8.6 while threshold to drop packet is 8.5
+ testAttributes->m_setAccuProb = 8.6;
+ EnqueueWithDelay (queue, pktSize, 400, testAttributes);
+ DequeueWithDelay (queue, 0.014, 400);
+ Simulator::Stop (Seconds (8.0));
+ Simulator::Run ();
+ st = queue->GetStats ();
+ uint32_t test14 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
+ NS_TEST_EXPECT_MSG_EQ (test14, testAttributes->m_expectedDrops,
+ "The number of unforced drops should be equal to number of expected unforced drops");
+ NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
}
void
-PieQueueDiscTestCase::Enqueue (Ptr queue, uint32_t size, uint32_t nPkt)
+PieQueueDiscTestCase::Enqueue (Ptr queue, uint32_t size, uint32_t nPkt, Ptr testAttributes)
{
Address dest;
- for (uint32_t i = 0; i < nPkt; i++)
+ for (uint32_t i = 0; i < nPkt; i++)
+ {
+ if (testAttributes->m_constAccuProb)
+ {
+ queue->m_accuProb = testAttributes->m_setAccuProb;
+ if (testAttributes->m_checkMaxAccuProb)
+ {
+ CheckMaxAccuProb (queue, testAttributes);
+ }
+ }
+ queue->Enqueue (Create (Create (size), dest, testAttributes->m_ecnCapable));
+ if (testAttributes->m_checkProb)
+ {
+ CheckDropProb (queue, testAttributes);
+ }
+ if (testAttributes->m_checkAccuProb)
+ {
+ CheckAccuProb (queue, testAttributes);
+ }
+ }
+}
+
+void
+PieQueueDiscTestCase::CheckDropProb (Ptr queue, Ptr testAttributes)
+{
+ double dropProb = queue->m_dropProb;
+ if (testAttributes->m_maxDropProb < dropProb)
+ {
+ testAttributes->m_maxDropProb = dropProb;
+ }
+ if (testAttributes->m_prevDropProb > 0.1)
+ {
+ double currentDiff = dropProb - testAttributes->m_prevDropProb;
+ if (testAttributes->m_maxDropProbDiff < currentDiff)
+ {
+ testAttributes->m_maxDropProbDiff = currentDiff;
+ }
+ }
+ testAttributes->m_prevDropProb = dropProb;
+}
+
+void
+PieQueueDiscTestCase::CheckAccuProb (Ptr queue, Ptr testAttributes)
+{
+ double dropProb = queue->m_dropProb;
+ double accuProb = queue->m_accuProb;
+ if (accuProb != 0)
+ {
+ double expectedAccuProb = testAttributes->m_prevAccuProb + dropProb;
+ testAttributes->m_accuProbError = accuProb - expectedAccuProb;
+ }
+ testAttributes->m_prevAccuProb = accuProb;
+}
+
+void
+PieQueueDiscTestCase::CheckMaxAccuProb (Ptr queue, Ptr testAttributes)
+{
+ queue->m_dropProb = 0.001;
+ QueueSize queueSize = queue->GetCurrentSize ();
+ if ((queueSize.GetUnit () == QueueSizeUnit::PACKETS && queueSize.GetValue () > 2) || (queueSize.GetUnit () == QueueSizeUnit::BYTES && queueSize.GetValue () > 2000))
{
- queue->Enqueue (Create (Create (size), dest));
+ testAttributes->m_expectedDrops = testAttributes->m_expectedDrops + 1;
}
}
void
-PieQueueDiscTestCase::EnqueueWithDelay (Ptr queue, uint32_t size, uint32_t nPkt)
+PieQueueDiscTestCase::EnqueueWithDelay (Ptr queue, uint32_t size, uint32_t nPkt, Ptr testAttributes)
{
Address dest;
double delay = 0.01; // enqueue packets with delay
for (uint32_t i = 0; i < nPkt; i++)
{
- Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Enqueue, this, queue, size, 1);
+ Simulator::Schedule (Time (Seconds ((i + 1) * delay)), &PieQueueDiscTestCase::Enqueue, this, queue, size, 1, testAttributes);
}
}