24 #include "ns3/codel-queue-disc.h" 25 #include "ns3/packet.h" 26 #include "ns3/uinteger.h" 27 #include "ns3/string.h" 28 #include "ns3/double.h" 30 #include "ns3/simulator.h" 35 #define REC_INV_SQRT_BITS_ns3 (8 * sizeof(uint16_t)) 38 #define REC_INV_SQRT_SHIFT_ns3 (32 - REC_INV_SQRT_BITS_ns3) 43 uint32_t invsqrt2 = ((uint64_t)invsqrt * invsqrt) >> 32;
44 uint64_t val = (3LL << 32) - ((uint64_t)count * invsqrt2);
47 val = (val * invsqrt) >> (32 - 2 + 1);
53 return (uint32_t)(((uint64_t)val * ep_ro) >> 32);
74 virtual void AddHeader (
void);
75 virtual bool Mark(
void);
95 m_ecnCapablePacket (ecnCapable)
133 virtual void DoRun (
void);
140 :
TestCase (
"Basic enqueue and dequeue operations, and attribute setting")
151 uint32_t modeSize = 0;
156 "Verify that we can actually set the attribute MinBytes");
158 "Verify that we can actually set the attribute Interval");
160 "Verify that we can actually set the attribute Target");
171 true,
"Verify that we can actually set the attribute MaxSize");
183 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p1, dest,
false));
185 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p2, dest,
false));
187 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p3, dest,
false));
189 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p4, dest,
false));
191 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p5, dest,
false));
193 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p6, dest,
false));
197 0,
"There should be no packets being dropped due to full queue");
209 NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p2->GetUid (),
"Was this the second packet ?");
219 NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetUid (), p4->GetUid (),
"Was this the fourth packet ?");
235 "There should be no packet drops according to CoDel algorithm");
253 virtual void DoRun (
void);
267 :
TestCase (
"Basic overflow behavior")
277 uint32_t modeSize = 0;
296 true,
"Verify that we can actually set the attribute MaxSize");
298 "Verify that we can actually set the attribute MinBytes");
303 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p1, dest,
false));
304 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p2, dest,
false));
305 queue->
Enqueue (Create<CodelQueueDiscTestItem> (p3, dest,
false));
309 3,
"There should be three packets being dropped due to full queue");
316 for (uint32_t i = 0; i < nPkt; i++)
318 queue->
Enqueue (Create<CodelQueueDiscTestItem> (Create<Packet> (size), dest,
false));
332 virtual void DoRun (
void);
336 :
TestCase (
"NewtonStep arithmetic unit test")
348 for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
350 for (uint32_t count = 1; count < 0xff; count *= 2)
352 result = queue->
NewtonStep (recInvSqrt, count);
355 "ns-3 NewtonStep() fails to match Linux equivalent");
370 virtual void DoRun (
void);
381 :
TestCase (
"ControlLaw arithmetic unit test")
402 uint32_t codelTimeVal;
405 for (uint16_t recInvSqrt = 0xff; recInvSqrt > 0; recInvSqrt /= 2)
408 uint32_t ns3Result = queue->
ControlLaw (codelTimeVal, interval, recInvSqrt);
410 NS_TEST_EXPECT_MSG_EQ (ns3Result, linuxResult,
"Linux result for ControlLaw should equal ns-3 result");
430 virtual void DoRun (
void);
456 :
TestCase (
"Basic drop operations")
475 uint32_t modeSize = 0;
487 true,
"Verify that we can actually set the attribute MaxSize");
500 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->
GetInterval ();
512 Simulator::Destroy ();
519 for (uint32_t i = 0; i < nPkt; i++)
521 queue->
Enqueue (Create<CodelQueueDiscTestItem> (Create<Packet> (size), dest,
false));
532 uint32_t currentDropCount = 0;
534 if (initialDropCount > 0 && currentTime.
GetMicroSeconds () >= initialDropNext)
539 if (initialQSize != 0)
542 if (initialDropCount == 0 && currentTime > queue->
GetTarget ())
544 if (currentTime < queue->GetInterval ())
548 "Sojourn time has just gone above target from below." 549 "Hence, there should be no packet drops");
557 "We enter the dropping state, perform initial packet drop, and dequeue the next." 558 "So there should be 2 more packets dequeued.");
562 else if (initialDropCount > 0)
568 "Sojourn is still above target." 569 "However, it's not time for next drop." 570 "So there should be only 1 more packet dequeued");
572 NS_TEST_EXPECT_MSG_EQ (currentDropCount, 1,
"There should still be only 1 packet drop from the last dequeue");
578 "It's time for next drop." 579 "The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");
601 virtual void DoRun (
void);
631 :
TestCase (
"Basic mark operations")
657 uint32_t modeSize = 0;
671 true,
"Verify that we can actually set the attribute MaxSize");
673 true,
"Verify that we can actually set the attribute UseEcn");
687 Time waitUntilSecondDequeue = waitUntilFirstDequeue + 2 * queue->
GetInterval ();
691 Simulator::Destroy ();
694 queue = CreateObject<CoDelQueueDisc> ();
696 true,
"Verify that we can actually set the attribute MaxSize");
698 true,
"Verify that we can actually set the attribute UseEcn");
722 Simulator::Destroy ();
725 queue = CreateObject<CoDelQueueDisc> ();
727 true,
"Verify that we can actually set the attribute MaxSize");
729 true,
"Verify that we can actually set the attribute UseEcn");
731 true,
"Verify that we can actually set the attribute CeThreshold");
757 Simulator::Destroy ();
760 queue = CreateObject<CoDelQueueDisc> ();
762 true,
"Verify that we can actually set the attribute MaxSize");
764 true,
"Verify that we can actually set the attribute UseEcn");
766 true,
"Verify that we can actually set the attribute CeThreshold");
788 Simulator::Destroy ();
795 for (uint32_t i = 0; i < nPkt; i++)
797 queue->
Enqueue (Create<CodelQueueDiscTestItem> (Create<Packet> (size), dest, ecnCapable));
809 uint32_t currentDropCount = 0;
810 uint32_t currentTargetMarkCount = 0;
811 uint32_t currentCeThreshMarkCount = 0;
813 if (initialTargetMarkCount > 0 && currentTime.
GetMicroSeconds () >= initialDropNext && testCase == 3)
818 if (initialQSize != 0)
824 if (currentDropCount == 1)
829 else if (testCase == 2)
831 if (initialTargetMarkCount == 0 && currentTime > queue->
GetTarget ())
833 if (currentTime < queue->GetInterval ())
841 "Sojourn time has just gone above target from below." 842 "Hence, there should be no target exceeded marked packets");
844 "Hence, there should not be any CE threshold exceeded marked packet");
853 "We enter the dropping state and perform initial packet marking" 854 "So there should be only 1 more packet dequeued.");
856 NS_TEST_EXPECT_MSG_EQ (currentTargetMarkCount, 1,
"There should be 1 target exceeded marked packet");
857 NS_TEST_ASSERT_MSG_EQ (currentCeThreshMarkCount, 0,
"There should not be any CE threshold exceeded marked packet");
860 else if (initialTargetMarkCount > 0)
868 "Sojourn is still above target." 869 "However, it's not time for next target exceeded mark." 870 "So there should be only 1 more packet dequeued");
872 NS_TEST_EXPECT_MSG_EQ (currentTargetMarkCount, 1,
"There should still be only 1 target exceeded marked packet from the last dequeue");
873 NS_TEST_ASSERT_MSG_EQ (currentCeThreshMarkCount, 0,
"There should not be any CE threshold exceeded marked packet");
881 "It's time for packet to be marked" 882 "So there should be only 1 more packet dequeued");
886 "to number of packets in the queue before first mark as the behavior untill packet N should be the same.");
887 NS_TEST_ASSERT_MSG_EQ (currentCeThreshMarkCount, 0,
"There should not be any CE threshold exceeded marked packet");
891 else if (testCase == 3)
893 if (initialTargetMarkCount == 0 && currentTime > queue->
GetTarget ())
895 if (currentTime < queue->GetInterval ())
903 "Sojourn time has just gone above target from below." 904 "Hence, there should be no target exceeded marked packets");
906 "Hence, there should be 1 CE threshold exceeded marked packet");
914 "We enter the dropping state and perform initial packet marking" 915 "So there should be only 1 more packet dequeued.");
917 NS_TEST_EXPECT_MSG_EQ (currentTargetMarkCount, 1,
"There should be 1 target exceeded marked packet");
918 NS_TEST_EXPECT_MSG_EQ (currentCeThreshMarkCount, 1,
"There should be 1 CE threshold exceeded marked packets");
921 else if (initialTargetMarkCount > 0)
929 "Sojourn is still above target." 930 "However, it's not time for next target exceeded mark." 931 "So there should be only 1 more packet dequeued");
933 NS_TEST_EXPECT_MSG_EQ (currentTargetMarkCount, 1,
"There should still be only 1 target exceeded marked packet from the last dequeue");
934 NS_TEST_EXPECT_MSG_EQ (currentCeThreshMarkCount, 2,
"There should be 2 CE threshold exceeded marked packets");
942 "It's time for packet to be dropped as packets are not ecnCapable" 943 "The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");
945 NS_TEST_EXPECT_MSG_EQ (currentTargetMarkCount, 1,
"There should still be only 1 target exceeded marked packet");
946 NS_TEST_EXPECT_MSG_EQ (currentCeThreshMarkCount, 2,
"There should still be 2 CE threshold exceeded marked packet as packets are not ecnCapable");
950 else if (testCase == 4)
952 if (currentTime < queue->GetTarget ())
954 if (initialCeThreshMarkCount == 0 && currentTime <
MilliSeconds (2))
961 "Hence, there should not be any CE threshold exceeded marked packet");
970 "There should be 1 CE threshold exceeded marked packet");
973 else if (initialCeThreshMarkCount > 0 && currentTime < queue->GetInterval ())
975 if (initialCeThreshMarkCount < 2)
981 NS_TEST_EXPECT_MSG_EQ (currentCeThreshMarkCount, 2,
"There should be 2 CE threshold exceeded marked packets");
989 NS_TEST_EXPECT_MSG_EQ (currentCeThreshMarkCount, 3,
"There should be 3 CE threshold exceeded marked packet");
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint64_t GetUid(void) const
Returns the packet's Uid.
Simulation virtual time values and global simulation resolution.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static uint32_t ControlLaw(uint32_t t, uint32_t interval, uint32_t recInvSqrt)
Determine the time for next drop CoDel control law is t + m_interval/sqrt(m_count).
Codel Queue Disc Test Item.
AttributeValue implementation for Boolean.
Class for representing queue sizes.
Test 6: enqueue/dequeue with marks according to CoDel algorithm.
bool Enqueue(Ptr< QueueDiscItem > item)
Pass a packet to store to the queue discipline.
uint32_t nPacketsBeforeFirstDrop
Number of packets in the queue before first drop.
CoDelQueueDiscControlLawTest()
CoDelQueueDiscTestSuite()
Hold variables of type string.
uint32_t GetValue() const
Get the underlying value.
uint32_t GetDropNext(void)
Get the time for next packet drop while in the dropping state.
QueueSizeUnit
Enumeration of the operating modes of queues.
virtual void DoRun(void)
Implementation to actually run this TestCase.
QueueSize GetCurrentSize(void)
Get the current size of the queue disc in bytes, if operating in bytes mode, or packets, otherwise.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define REC_INV_SQRT_SHIFT_ns3
Test 5: enqueue/dequeue with drops according to CoDel algorithm.
Time GetInterval(void)
Get the interval.
Test 3: NewtonStep unit test - test against explicit port of Linux implementation.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
bool m_ecnCapablePacket
ECN capable packet?
#define NS_UNUSED(x)
Mark a local variable as unused.
void Dequeue(Ptr< CoDelQueueDisc > queue, uint32_t modeSize)
Dequeue function.
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
uint32_t nPacketsBeforeFirstMark
Number of packets in the queue before first mark.
QueueDiscItem is the abstract base class for items that are stored in a queue disc.
CoDelQueueDiscNewtonStepTest()
static uint16_t NewtonStep(uint16_t recInvSqrt, uint32_t count)
Calculate the reciprocal square root of m_count by using Newton's method http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots m_recInvSqrt (new) = (m_recInvSqrt (old) / 2) * (3 - m_count * m_recInvSqrt^2)
void DropNextTracer(uint32_t oldVal, uint32_t newVal)
Drop next tracer function.
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
a polymophic address class
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
AttributeValue implementation for Time.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt, bool ecnCapable)
Enqueue function.
Hold an unsigned integer type.
uint32_t GetNDroppedPackets(std::string reason) const
Get the number of packets dropped for the given reason.
virtual bool Mark(void)
Marks the packet as a substitute for dropping it, such as for Explicit Congestion Notification...
Use number of packets for queue size.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
virtual void AddHeader(void)
Add the header to the packet.
static uint16_t _codel_Newton_step(uint16_t rec_inv_sqrt, uint32_t count)
const Stats & GetStats(void)
Retrieve all the collected statistics.
CoDelQueueDiscBasicOverflow(QueueSizeUnit mode)
Constructor.
CoDelQueueDiscBasicDrop(QueueSizeUnit mode)
Constructor.
void DropNextTracer(uint32_t oldVal, uint32_t newVal)
Drop next tracer function.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< QueueDiscItem > Dequeue(void)
Extract from the queue disc the packet that has been dequeued by calling Peek, if any...
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetNMarkedPackets(std::string reason) const
Get the number of packets marked for the given reason.
Time GetTarget(void)
Get the target queue delay.
uint32_t m_dropNextCount
count the number of times m_dropNext is recalculated
void Enqueue(Ptr< CoDelQueueDisc > queue, uint32_t size, uint32_t nPkt)
Enqueue function.
CoDelQueueDiscTestSuite g_coDelQueueTestSuite
the test suite
void Dequeue(Ptr< CoDelQueueDisc > queue, uint32_t modeSize, uint32_t testCase)
Dequeue function.
uint32_t Time2CoDel(Time t)
Return the unsigned 32-bit integer representation of the input Time object.
CoDel Queue Disc Test Suite.
Time Seconds(double value)
Construct a Time in the indicated unit.
virtual ~CodelQueueDiscTestItem()
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
static uint32_t _reciprocal_scale(uint32_t val, uint32_t ep_ro)
This test suite implements a Unit Test.
uint32_t pktSize
packet size used for the simulation (in bytes)
Use number of bytes for queue size.
Test 4: ControlLaw unit test - test against explicit port of Linux implementation.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test 1: simple enqueue/dequeue with no drops.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
uint32_t _codel_control_law(uint32_t t, uint32_t interval, uint32_t recInvSqrt)
Codel control law function.
CoDelQueueDiscBasicMark(QueueSizeUnit mode)
Constructor.
Test 2: enqueue with drops due to queue overflow.
CoDelQueueDiscBasicEnqueueDequeue(QueueSizeUnit mode)
Constructor.