traffic-control: Add ECN tests for COBALT queue disc
This commit is contained in:
committed by
Tom Henderson
parent
32e95f8228
commit
830edb7623
@@ -120,6 +120,7 @@ The suite includes 2 test cases:
|
||||
* Test 1: Simple enqueue/dequeue with no drops.
|
||||
* Test 2: Change of BLUE's drop probability upon queue full
|
||||
(Activation of Blue).
|
||||
* Test 3: Test for ECN marking of packets
|
||||
|
||||
The test suite can be run using the following commands:
|
||||
|
||||
|
||||
@@ -323,6 +323,320 @@ CobaltQueueDiscDropTest::DoRun (void)
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup traffic-control-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Test 3: Cobalt Queue Disc ECN marking Test Item
|
||||
*/
|
||||
class CobaltQueueDiscMarkTest : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param mode the mode
|
||||
*/
|
||||
CobaltQueueDiscMarkTest (QueueSizeUnit mode);
|
||||
virtual void DoRun (void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Enqueue function
|
||||
* \param queue the queue disc
|
||||
* \param size the size
|
||||
* \param nPkt the number of packets
|
||||
* \param ecnCapable ECN capable traffic
|
||||
*/
|
||||
void Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable);
|
||||
/**
|
||||
* \brief Dequeue function
|
||||
* \param queue the queue disc
|
||||
* \param modeSize the mode size
|
||||
* \param testCase the test case number
|
||||
*/
|
||||
void Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase);
|
||||
/**
|
||||
* \brief Drop next tracer function
|
||||
* \param oldVal the old value of m_dropNext
|
||||
* \param newVal the new value of m_dropNext
|
||||
*/
|
||||
void DropNextTracer (int64_t oldVal, int64_t newVal);
|
||||
QueueSizeUnit m_mode; ///< mode
|
||||
uint32_t m_dropNextCount; ///< count the number of times m_dropNext is recalculated
|
||||
uint32_t nPacketsBeforeFirstDrop; ///< Number of packets in the queue before first drop
|
||||
uint32_t nPacketsBeforeFirstMark; ///< Number of packets in the queue before first mark
|
||||
};
|
||||
|
||||
CobaltQueueDiscMarkTest::CobaltQueueDiscMarkTest (QueueSizeUnit mode)
|
||||
: TestCase ("Basic mark operations")
|
||||
{
|
||||
m_mode = mode;
|
||||
m_dropNextCount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CobaltQueueDiscMarkTest::DropNextTracer (int64_t oldVal, int64_t newVal)
|
||||
{
|
||||
NS_UNUSED (oldVal);
|
||||
NS_UNUSED (newVal);
|
||||
m_dropNextCount++;
|
||||
}
|
||||
|
||||
void
|
||||
CobaltQueueDiscMarkTest::DoRun (void)
|
||||
{
|
||||
// Test is divided into 3 sub test cases:
|
||||
// 1) Packets are not ECN capable.
|
||||
// 2) Packets are ECN capable.
|
||||
// 3) Some packets are ECN capable.
|
||||
|
||||
// Test case 1
|
||||
Ptr<CobaltQueueDisc> queue = CreateObject<CobaltQueueDisc> ();
|
||||
uint32_t pktSize = 1000;
|
||||
uint32_t modeSize = 0;
|
||||
nPacketsBeforeFirstDrop = 0;
|
||||
nPacketsBeforeFirstMark = 0;
|
||||
|
||||
if (m_mode == QueueSizeUnit::BYTES)
|
||||
{
|
||||
modeSize = pktSize;
|
||||
}
|
||||
else if (m_mode == QueueSizeUnit::PACKETS)
|
||||
{
|
||||
modeSize = 1;
|
||||
}
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
|
||||
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");
|
||||
|
||||
queue->Initialize ();
|
||||
|
||||
// Not-ECT traffic to induce packet drop
|
||||
Enqueue (queue, pktSize, 20, false);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
|
||||
|
||||
// Although the first dequeue occurs with a sojourn time above target
|
||||
// there should not be any dropped packets in this interval
|
||||
Time waitUntilFirstDequeue = 2 * queue->GetTarget ();
|
||||
Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
|
||||
|
||||
// This dequeue should cause a packet to be dropped
|
||||
Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->GetInterval ();
|
||||
Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 1);
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
// Test case 2, queue with ECN capable traffic for marking of packets instead of dropping
|
||||
queue = CreateObject<CobaltQueueDisc> ();
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
|
||||
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");
|
||||
|
||||
queue->Initialize ();
|
||||
|
||||
// ECN capable traffic
|
||||
Enqueue (queue, pktSize, 20, true);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
|
||||
|
||||
// Although the first dequeue occurs with a sojourn time above target
|
||||
// there should not be any marked packets in this interval
|
||||
Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
|
||||
|
||||
// This dequeue should cause a packet to be marked
|
||||
Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
|
||||
|
||||
// This dequeue should cause a packet to be marked as dropnext is equal to current time
|
||||
Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
|
||||
|
||||
// In dropping phase and it's time for next packet to be marked
|
||||
// the dequeue should cause additional packet to be marked
|
||||
Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 2);
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
// Test case 3, some packets are ECN capable
|
||||
queue = CreateObject<CobaltQueueDisc> ();
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxSize", QueueSizeValue (QueueSize (m_mode, modeSize * 500))),
|
||||
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");
|
||||
|
||||
queue->Initialize ();
|
||||
|
||||
// First 3 packets in the queue are ecnCapable
|
||||
Enqueue (queue, pktSize, 3, true);
|
||||
// Rest of the packet are not ecnCapable
|
||||
Enqueue (queue, pktSize, 17, false);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), 20 * modeSize, "There should be 20 packets in queue.");
|
||||
|
||||
// Although the first dequeue occurs with a sojourn time above target
|
||||
// there should not be any marked packets in this interval
|
||||
Simulator::Schedule (waitUntilFirstDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
|
||||
|
||||
// This dequeue should cause a packet to be marked
|
||||
Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
|
||||
|
||||
// This dequeue should cause a packet to be marked as dropnext is equal to current time
|
||||
Simulator::Schedule (waitUntilSecondDequeue, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
|
||||
|
||||
// In dropping phase and it's time for next packet to be dropped as packets are not ECN capable
|
||||
// the dequeue should cause packet to be dropped
|
||||
Simulator::Schedule (waitUntilSecondDequeue * 2, &CobaltQueueDiscMarkTest::Dequeue, this, queue, modeSize, 3);
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
void
|
||||
CobaltQueueDiscMarkTest::Enqueue (Ptr<CobaltQueueDisc> queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
|
||||
{
|
||||
Address dest;
|
||||
for (uint32_t i = 0; i < nPkt; i++)
|
||||
{
|
||||
queue->Enqueue (Create<CobaltQueueDiscTestItem> (Create<Packet> (size), dest, 0, ecnCapable));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CobaltQueueDiscMarkTest::Dequeue (Ptr<CobaltQueueDisc> queue, uint32_t modeSize, uint32_t testCase)
|
||||
{
|
||||
uint32_t initialMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
uint32_t initialQSize = queue->GetCurrentSize ().GetValue ();
|
||||
uint32_t initialDropNext = queue->GetDropNext ();
|
||||
Time currentTime = Simulator::Now ();
|
||||
uint32_t currentDropCount = 0;
|
||||
uint32_t currentMarkCount = 0;
|
||||
|
||||
if (initialMarkCount > 0 && currentTime.GetNanoSeconds () > initialDropNext && testCase == 3)
|
||||
{
|
||||
queue->TraceConnectWithoutContext ("DropNext", MakeCallback (&CobaltQueueDiscMarkTest::DropNextTracer, this));
|
||||
}
|
||||
|
||||
if (initialQSize != 0)
|
||||
{
|
||||
Ptr<QueueDiscItem> item = queue->Dequeue ();
|
||||
if (testCase == 1)
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
if (currentDropCount != 0)
|
||||
{
|
||||
nPacketsBeforeFirstDrop = initialQSize;
|
||||
}
|
||||
}
|
||||
if (testCase == 2)
|
||||
{
|
||||
if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
|
||||
{
|
||||
if (currentTime < queue->GetInterval ())
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_ASSERT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
|
||||
"Sojourn time has just gone above target from below."
|
||||
"Hence, there should be no marked packets");
|
||||
}
|
||||
else if (currentTime >= queue->GetInterval ())
|
||||
{
|
||||
nPacketsBeforeFirstMark = initialQSize;
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
|
||||
"Sojourn time has been above target for at least interval."
|
||||
"We enter the dropping state and perform initial packet marking"
|
||||
"So there should be only 1 more packet dequeued.");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
|
||||
}
|
||||
}
|
||||
else if (initialMarkCount > 0)
|
||||
{
|
||||
if (currentTime.GetNanoSeconds () <= initialDropNext)
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
|
||||
"Sojourn is still above target."
|
||||
"There should be only 1 more packet dequeued");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet as."
|
||||
"current dropnext is equal to current time.");
|
||||
}
|
||||
else if (currentTime.GetNanoSeconds () > initialDropNext)
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
|
||||
"It's time for packet to be marked"
|
||||
"So there should be only 1 more packet dequeued");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 3, "There should be 3 marked packet");
|
||||
NS_TEST_EXPECT_MSG_EQ (nPacketsBeforeFirstDrop, nPacketsBeforeFirstMark, "Number of packets in the queue before drop should be equal"
|
||||
"to number of packets in the queue before first mark as the behavior until packet N should be the same.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (testCase == 3)
|
||||
{
|
||||
if (initialMarkCount == 0 && currentTime > queue->GetTarget ())
|
||||
{
|
||||
if (currentTime < queue->GetInterval ())
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "There should be 1 packet dequeued.");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_ASSERT_MSG_EQ (currentMarkCount, 0, "We are not in dropping state."
|
||||
"Sojourn time has just gone above target from below."
|
||||
"Hence, there should be no marked packets");
|
||||
}
|
||||
else if (currentTime >= queue->GetInterval ())
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize,
|
||||
"Sojourn time has been above target for at least interval."
|
||||
"We enter the dropping state and perform initial packet marking"
|
||||
"So there should be only 1 more packet dequeued.");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 1, "There should be 1 marked packet");
|
||||
}
|
||||
}
|
||||
else if (initialMarkCount > 0)
|
||||
{
|
||||
if (currentTime.GetNanoSeconds () <= initialDropNext)
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - modeSize, "We are in dropping state."
|
||||
"Sojourn is still above target."
|
||||
"So there should be only 1 more packet dequeued");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "There should not be any packet drops");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should be 2 marked packet"
|
||||
"as dropnext is equal to current time");
|
||||
}
|
||||
else if (currentTime.GetNanoSeconds () > initialDropNext)
|
||||
{
|
||||
currentDropCount = queue->GetStats ().GetNDroppedPackets (CobaltQueueDisc::TARGET_EXCEEDED_DROP);
|
||||
currentMarkCount = queue->GetStats ().GetNMarkedPackets (CobaltQueueDisc::FORCED_MARK);
|
||||
NS_TEST_EXPECT_MSG_EQ (queue->GetCurrentSize ().GetValue (), initialQSize - (m_dropNextCount + 1) * modeSize, "We are in dropping state."
|
||||
"It's time for packet to be dropped as packets are not ecnCapable"
|
||||
"The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentDropCount, m_dropNextCount, "The number of drops equals to the number of times m_dropNext is updated");
|
||||
NS_TEST_EXPECT_MSG_EQ (currentMarkCount, 2, "There should still be only 2 marked packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class CobaltQueueDiscTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
@@ -334,5 +648,8 @@ public:
|
||||
AddTestCase (new CobaltQueueDiscBasicEnqueueDequeue (BYTES), TestCase::QUICK);
|
||||
// Test 2: Drop test
|
||||
AddTestCase (new CobaltQueueDiscDropTest (), TestCase::QUICK);
|
||||
// Test 3: Mark test
|
||||
AddTestCase (new CobaltQueueDiscMarkTest (PACKETS), TestCase::QUICK);
|
||||
AddTestCase (new CobaltQueueDiscMarkTest (BYTES), TestCase::QUICK);
|
||||
}
|
||||
} g_cobaltQueueTestSuite; ///< the test suite
|
||||
|
||||
Reference in New Issue
Block a user