traffic-control: Record reasons for dropping and marking packets

This commit is contained in:
Stefano Avallone
2017-09-14 18:12:34 +02:00
parent 4d6efe731b
commit eb0351dccb
25 changed files with 568 additions and 272 deletions

View File

@@ -95,13 +95,33 @@ us a note on ns-developers mailing list.</p>
</li>
<li>MqQueueDisc, a multi-queue aware queue disc modelled after the mq qdisc in Linux, has been introduced.
</li>
<li>Added <b>QueueDisc::GetStats()</b> which returns detailed statistics about the operations of a queue disc.
Consequently, a number of methods of the QueueDisc class have been removed: <b>GetTotalReceivedPackets()</b>,
<b>GetTotalReceivedBytes()</b>, <b>GetTotalDroppedPackets()</b>, <b>GetTotalDroppedBytes()</b>,
<b>GetTotalRequeuedPackets()</b>, <b>GetTotalRequeuedBytes()</b>.
</li>
<li>Two new methods, <b>QueueDisc::DropBeforeEnqueue()</b> and <b>QueueDisc::DropAfterDequeue()</b> have
been introduced to replace <b>QueueDisc::Drop()</b>. Correspondingly, two new trace sources have been added to the QueueDisc class: DropBeforeEnqueue and DropAfterDequeue.
been introduced to replace <b>QueueDisc::Drop()</b>. These new methods require the caller to specify the
reason why a packet was dropped. Correspondingly, two new trace sources ("DropBeforeEnqueue" and
"DropAfterDequeue") have been added to the QueueDisc class, providing both the items that were dropped
and the reason why they were dropped.
</li>
<li>Added <b>QueueDisc::GetStats()</b> which returns detailed statistics about the operations of
a queue disc. Statistics can be accessed through the member variables of the returned object and
by calling the <b>GetNDroppedPackets()</b>, <b>GetNDroppedBytes()</b>, <b>GetNMarkedPackets()</b> and <b>GetNMarkedBytes()</b> methods on the returned object. Such methods return the number of packets/bytes
dropped/marked for the specified reason (passed as argument). Consequently:
<ul>
<li>A number of methods of the QueueDisc class have been removed: <b>GetTotalReceivedPackets()</b>,
<b>GetTotalReceivedBytes()</b>, <b>GetTotalDroppedPackets()</b>, <b>GetTotalDroppedBytes()</b>,
<b>GetTotalRequeuedPackets()</b>, <b>GetTotalRequeuedBytes()</b>.</li>
<li>The <b>Stats</b> struct and the <b>GetStats()</b> method of <b>RedQueueDisc</b> and <b>PieQueueDisc</b> have been removed and replaced by those of the QueueDisc base class.</li>
<li>The <b>GetDropOverLimit</b> and <b>GetDropCount</b> methods of <b>CoDelQueueDisc</b> have been removed.
The values they returned can be obtained by calling, respectively,
GetStats ().GetNDroppedPackets (CoDelQueueDisc::OVERLIMIT_DROP) and
GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP). The "DropCount" trace of
<b>CoDelQueueDisc</b> has been removed as well. Packets dropped because the target is exceeded can
be obtained through the new "DropAfterDequeue" trace of the QueueDisc class.</li>
</ul>
</li>
<li> The new <b>QueueDisc::Mark()</b> method has been introduced to allow subclasses to request to mark a packet.
The caller must specify the reason why the packet must be marked. Correspondingly, a new trace source ("Mark")
has been added to the QueueDisc class, providing both the items that were marked and the reason why they
were marked.
</li>
<li>A new trace source, <b>SojournTime</b>, is exported by the QueueDisc base class to provide the
sojourn time of every packet dequeued from a queue disc. This has been made possible by adding a

View File

@@ -165,24 +165,22 @@ int main (int argc, char *argv[])
std::cout << "Running the simulation" << std::endl;
Simulator::Run ();
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
if (st.unforcedDrop == 0)
if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0)
{
std::cout << "There should be some unforced drops" << std::endl;
exit (1);
}
if (st.qLimDrop != 0)
if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0)
{
std::cout << "There should be zero drops due to queue full" << std::endl;
exit (1);
}
std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl;
std::cout << st << std::endl;
std::cout << "Destroying the simulation" << std::endl;
Simulator::Destroy ();

View File

@@ -167,24 +167,22 @@ int main (int argc, char *argv[])
std::cout << "Running the simulation" << std::endl;
Simulator::Run ();
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
if (st.unforcedDrop == 0)
if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0)
{
std::cout << "There should be some unforced drops" << std::endl;
exit (1);
}
if (st.qLimDrop != 0)
if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0)
{
std::cout << "There should be zero drops due to queue full" << std::endl;
exit (1);
}
std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl;
std::cout << st << std::endl;
std::cout << "Destroying the simulation" << std::endl;
Simulator::Destroy ();

View File

@@ -81,7 +81,7 @@ DevicePacketsInQueueTrace (uint32_t oldValue, uint32_t newValue)
void
SojournTimeTrace (Time oldValue, Time newValue)
{
std::cout << "Sojourn time " << newValue << std::endl;
std::cout << "Sojourn time " << newValue.ToDouble (Time::MS) << "ms" << std::endl;
}
int

View File

@@ -70,6 +70,12 @@ of the queue disc. The following identities hold:
* queued = enqueued - dequeued
* sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
Separate counters are also kept for each possible reason to drop a packet.
When a packet is dropped by an internal queue, e.g., because the queue is full,
the reason is "Dropped by internal queue". When a packet is dropped by a child
queue disc, the reason is "(Dropped by child queue disc) " followed by the
reason why the child queue disc dropped the packet.
The QueueDisc base class provides the SojournTime trace source, which provides
the sojourn time of every packet dequeued from a queue disc, including packets
that are dropped or requeued after being dequeued. The sojourn time is taken

View File

@@ -479,9 +479,9 @@ main (int argc, char *argv[])
Simulator::Stop (Seconds (sink_stop_time));
Simulator::Run ();
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
if (st.unforcedDrop == 0)
if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0)
{
std::cout << "There should be some unforced drops" << std::endl;
exit (1);
@@ -489,7 +489,7 @@ main (int argc, char *argv[])
if (aredTest == 1 || aredTest == 2 || aredTest == 13)
{
if (st.qLimDrop == 0)
if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) == 0)
{
std::cout << "There should be some drops due to queue full" << std::endl;
exit (1);
@@ -497,7 +497,7 @@ main (int argc, char *argv[])
}
else
{
if (st.qLimDrop != 0)
if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0)
{
std::cout << "There should be zero drops due to queue full" << std::endl;
exit (1);
@@ -515,9 +515,7 @@ main (int argc, char *argv[])
if (printAredStats)
{
std::cout << "*** ARED stats from Node 2 queue ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl;
std::cout << st << std::endl;
}
Simulator::Destroy ();

View File

@@ -304,9 +304,9 @@ main (int argc, char *argv[])
Simulator::Stop (Seconds (sink_stop_time));
Simulator::Run ();
PieQueueDisc::Stats st = StaticCast<PieQueueDisc> (queueDiscs.Get (0))->GetStats ();
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
if (st.forcedDrop != 0)
if (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP) != 0)
{
std::cout << "There should be no drops due to queue full." << std::endl;
exit (1);
@@ -323,8 +323,10 @@ main (int argc, char *argv[])
if (printPieStats)
{
std::cout << "*** PIE stats from Node 2 queue ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due to queue limits" << std::endl;
std::cout << "\t " << st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP)
<< " drops due to prob mark" << std::endl;
std::cout << "\t " << st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP)
<< " drops due to queue limits" << std::endl;
}
Simulator::Destroy ();

View File

@@ -458,17 +458,13 @@ main (int argc, char *argv[])
if (printRedStats)
{
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
std::cout << "*** RED stats from Node 2 queue ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due queue full" << std::endl;
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
std::cout << "*** RED stats from Node 2 queue disc ***" << std::endl;
std::cout << st << std::endl;
st = StaticCast<RedQueueDisc> (queueDiscs.Get (1))->GetStats ();
std::cout << "*** RED stats from Node 3 queue ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due queue full" << std::endl;
st = queueDiscs.Get (1)->GetStats ();
std::cout << "*** RED stats from Node 3 queue disc ***" << std::endl;
std::cout << st << std::endl;
}
Simulator::Destroy ();

View File

@@ -166,24 +166,22 @@ int main (int argc, char *argv[])
std::cout << "Running the simulation" << std::endl;
Simulator::Run ();
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queueDiscs.Get (0))->GetStats ();
QueueDisc::Stats st = queueDiscs.Get (0)->GetStats ();
if (st.unforcedDrop == 0)
if (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP) == 0)
{
std::cout << "There should be some unforced drops" << std::endl;
exit (1);
}
if (st.qLimDrop != 0)
if (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP) != 0)
{
std::cout << "There should be zero drops due to queue full" << std::endl;
exit (1);
}
std::cout << "*** Stats from the bottleneck queue disc ***" << std::endl;
std::cout << "\t " << st.unforcedDrop << " drops due to prob mark" << std::endl;
std::cout << "\t " << st.forcedDrop << " drops due to hard mark" << std::endl;
std::cout << "\t " << st.qLimDrop << " drops due to queue full" << std::endl;
std::cout << st << std::endl;
std::cout << "Destroying the simulation" << std::endl;
Simulator::Destroy ();

View File

@@ -109,10 +109,6 @@ TypeId CoDelQueueDisc::GetTypeId (void)
"CoDel count",
MakeTraceSourceAccessor (&CoDelQueueDisc::m_count),
"ns3::TracedValueCallback::Uint32")
.AddTraceSource ("DropCount",
"CoDel drop count",
MakeTraceSourceAccessor (&CoDelQueueDisc::m_dropCount),
"ns3::TracedValueCallback::Uint32")
.AddTraceSource ("LastCount",
"CoDel lastcount",
MakeTraceSourceAccessor (&CoDelQueueDisc::m_lastCount),
@@ -134,7 +130,6 @@ CoDelQueueDisc::CoDelQueueDisc ()
: QueueDisc (),
m_maxBytes (),
m_count (0),
m_dropCount (0),
m_lastCount (0),
m_dropping (false),
m_recInvSqrt (~0U >> REC_INV_SQRT_SHIFT),
@@ -143,8 +138,7 @@ CoDelQueueDisc::CoDelQueueDisc ()
m_state1 (0),
m_state2 (0),
m_state3 (0),
m_states (0),
m_dropOverLimit (0)
m_states (0)
{
NS_LOG_FUNCTION (this);
}
@@ -192,21 +186,18 @@ bool
CoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
{
NS_LOG_FUNCTION (this << item);
Ptr<Packet> p = item->GetPacket ();
if (m_mode == QUEUE_DISC_MODE_PACKETS && (GetInternalQueue (0)->GetNPackets () + 1 > m_maxPackets))
{
NS_LOG_LOGIC ("Queue full (at max packets) -- dropping pkt");
DropBeforeEnqueue (item);
++m_dropOverLimit;
DropBeforeEnqueue (item, OVERLIMIT_DROP);
return false;
}
if (m_mode == QUEUE_DISC_MODE_BYTES && (GetInternalQueue (0)->GetNBytes () + item->GetSize () > m_maxBytes))
{
NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- dropping pkt");
DropBeforeEnqueue (item);
++m_dropOverLimit;
DropBeforeEnqueue (item, OVERLIMIT_DROP);
return false;
}
@@ -307,9 +298,8 @@ CoDelQueueDisc::DoDequeue (void)
// rates so high that the next drop should happen now,
// hence the while loop.
NS_LOG_LOGIC ("Sojourn time is still above target and it's time for next drop; dropping " << item);
DropAfterDequeue (item);
DropAfterDequeue (item, TARGET_EXCEEDED_DROP);
++m_dropCount;
++m_count;
NewtonStep ();
item = GetInternalQueue (0)->Dequeue ();
@@ -346,8 +336,7 @@ CoDelQueueDisc::DoDequeue (void)
{
// Drop the first packet and enter dropping state unless the queue is empty
NS_LOG_LOGIC ("Sojourn time goes above target, dropping the first packet " << item << " and entering the dropping state");
++m_dropCount;
DropAfterDequeue (item);
DropAfterDequeue (item, TARGET_EXCEEDED_DROP);
item = GetInternalQueue (0)->Dequeue ();
@@ -405,18 +394,6 @@ CoDelQueueDisc::GetQueueSize (void)
}
}
uint32_t
CoDelQueueDisc::GetDropOverLimit (void)
{
return m_dropOverLimit;
}
uint32_t
CoDelQueueDisc::GetDropCount (void)
{
return m_dropCount;
}
Time
CoDelQueueDisc::GetTarget (void)
{

View File

@@ -108,21 +108,6 @@ public:
*/
uint32_t GetQueueSize (void);
/**
* \brief Get the number of packets dropped when packets
* arrive at a full queue and cannot be enqueued.
*
* \returns The number of dropped packets
*/
uint32_t GetDropOverLimit (void);
/**
* \brief Get the number of packets dropped according to CoDel algorithm
*
* \returns The number of dropped packets
*/
uint32_t GetDropCount (void);
/**
* \brief Get the target queue delay
*
@@ -144,6 +129,10 @@ public:
*/
uint32_t GetDropNext (void);
// Reasons for dropping packets
static constexpr const char* TARGET_EXCEEDED_DROP = "Target exceeded drop"; //!< Sojourn time above target
static constexpr const char* OVERLIMIT_DROP = "Overlimit drop"; //!< Overlimit dropped packet
private:
friend class::CoDelQueueDiscNewtonStepTest; // Test code
friend class::CoDelQueueDiscControlLawTest; // Test code
@@ -242,7 +231,6 @@ private:
Time m_interval; //!< 100 ms sliding minimum time window width
Time m_target; //!< 5 ms target queue delay
TracedValue<uint32_t> m_count; //!< Number of packets dropped since entering drop state
TracedValue<uint32_t> m_dropCount; //!< Number of dropped packets according CoDel algorithm
TracedValue<uint32_t> m_lastCount; //!< Last number of packets dropped since entering drop state
TracedValue<bool> m_dropping; //!< True if in dropping state
uint16_t m_recInvSqrt; //!< Reciprocal inverse square root
@@ -252,7 +240,6 @@ private:
uint32_t m_state2; //!< Number of times we perform next drop while in dropping state
uint32_t m_state3; //!< Number of times we enter drop state and drop the fist packet
uint32_t m_states; //!< Total number of times we are in state 1, state 2, or state 3
uint32_t m_dropOverLimit; //!< The number of packets dropped due to full queue
QueueDiscMode m_mode; //!< The operating mode (Bytes or packets)
};

View File

@@ -128,8 +128,7 @@ TypeId FqCoDelQueueDisc::GetTypeId (void)
}
FqCoDelQueueDisc::FqCoDelQueueDisc ()
: m_quantum (0),
m_overlimitDroppedPackets (0)
: m_quantum (0)
{
NS_LOG_FUNCTION (this);
}
@@ -162,7 +161,7 @@ FqCoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
if (ret == PacketFilter::PF_NO_MATCH)
{
NS_LOG_ERROR ("No filter has been able to classify this packet, drop it.");
DropBeforeEnqueue (item);
DropBeforeEnqueue (item, UNCLASSIFIED_DROP);
return false;
}
@@ -387,12 +386,11 @@ FqCoDelQueueDisc::FqCoDelDrop (void)
do
{
item = qd->GetInternalQueue (0)->Remove ();
item = qd->GetInternalQueue (0)->Dequeue ();
DropAfterDequeue (item, OVERLIMIT_DROP);
len += item->GetSize ();
} while (++count < m_dropBatchSize && len < threshold);
m_overlimitDroppedPackets += count;
return index;
}

View File

@@ -126,6 +126,10 @@ public:
*/
uint32_t GetQuantum (void) const;
// Reasons for dropping packets
static constexpr const char* UNCLASSIFIED_DROP = "Unclassified drop"; //!< No packet filter able to classify packet
static constexpr const char* OVERLIMIT_DROP = "Overlimit drop"; //!< Overlimit dropped packets
private:
virtual bool DoEnqueue (Ptr<QueueDiscItem> item);
virtual Ptr<QueueDiscItem> DoDequeue (void);
@@ -146,8 +150,6 @@ private:
uint32_t m_flows; //!< Number of flow queues
uint32_t m_dropBatchSize; //!< Max number of packets dropped from the fat flow
uint32_t m_overlimitDroppedPackets; //!< Number of overlimit dropped packets
std::list<Ptr<FqCoDelFlow> > m_newFlows; //!< The list of new flows
std::list<Ptr<FqCoDelFlow> > m_oldFlows; //!< The list of old flows

View File

@@ -68,7 +68,7 @@ PfifoFastQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
if (GetNPackets () >= m_limit)
{
NS_LOG_LOGIC ("Queue disc limit exceeded -- dropping packet");
DropBeforeEnqueue (item);
DropBeforeEnqueue (item, LIMIT_EXCEEDED_DROP);
return false;
}

View File

@@ -62,6 +62,9 @@ public:
virtual ~PfifoFastQueueDisc();
// Reasons for dropping packets
static constexpr const char* LIMIT_EXCEEDED_DROP = "Queue disc limit exceeded"; //!< Packet dropped due to queue disc limit exceeded
private:
/**
* Priority to band map. Values are taken from the prio2band array used by

View File

@@ -164,13 +164,6 @@ PieQueueDisc::GetQueueSize (void)
}
}
PieQueueDisc::Stats
PieQueueDisc::GetStats ()
{
NS_LOG_FUNCTION (this);
return m_stats;
}
Time
PieQueueDisc::GetQueueDelay (void)
{
@@ -197,15 +190,13 @@ PieQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|| (GetMode () == QUEUE_DISC_MODE_BYTES && nQueued + item->GetSize () > m_queueLimit))
{
// Drops due to queue limit: reactive
DropBeforeEnqueue (item);
m_stats.forcedDrop++;
DropBeforeEnqueue (item, FORCED_DROP);
return false;
}
else if (DropEarly (item, nQueued))
{
// Early probability drop: proactive
DropBeforeEnqueue (item);
m_stats.unforcedDrop++;
DropBeforeEnqueue (item, UNFORCED_DROP);
return false;
}
@@ -232,8 +223,6 @@ PieQueueDisc::InitializeParams (void)
m_dqStart = 0;
m_burstState = NO_BURST;
m_qDelayOld = Time (Seconds (0));
m_stats.forcedDrop = 0;
m_stats.unforcedDrop = 0;
}
bool PieQueueDisc::DropEarly (Ptr<QueueDiscItem> item, uint32_t qSize)

View File

@@ -67,15 +67,6 @@ public:
*/
virtual ~PieQueueDisc ();
/**
* \brief Stats
*/
typedef struct
{
uint32_t unforcedDrop; //!< Early probability drops: proactive
uint32_t forcedDrop; //!< Drops due to queue limit: reactive
} Stats;
/**
* \brief Burst types
*/
@@ -131,13 +122,6 @@ public:
*/
Time GetQueueDelay (void);
/**
* \brief Get PIE statistics after running.
*
* \returns The drop statistics.
*/
Stats GetStats ();
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
@@ -148,6 +132,10 @@ public:
*/
int64_t AssignStreams (int64_t stream);
// 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
protected:
/**
* \brief Dispose of the object
@@ -180,8 +168,6 @@ private:
*/
void CalculateP ();
Stats m_stats; //!< PIE statistics
// ** Variables supplied by user
QueueDiscMode m_mode; //!< Mode (bytes or packets)
uint32_t m_queueLimit; //!< Queue limit in bytes / packets

View File

@@ -103,13 +103,86 @@ QueueDisc::Stats::Stats ()
nTotalDroppedBytesBeforeEnqueue (0),
nTotalDroppedBytesAfterDequeue (0),
nTotalRequeuedPackets (0),
nTotalRequeuedBytes (0)
nTotalRequeuedBytes (0),
nTotalMarkedPackets (0),
nTotalMarkedBytes (0)
{
}
uint32_t
QueueDisc::Stats::GetNDroppedPackets (std::string reason) const
{
uint32_t count = 0;
auto it = nDroppedPacketsBeforeEnqueue.find (reason);
if (it != nDroppedPacketsBeforeEnqueue.end ())
{
count += it->second;
}
it = nDroppedPacketsAfterDequeue.find (reason);
if (it != nDroppedPacketsAfterDequeue.end ())
{
count += it->second;
}
return count;
}
uint64_t
QueueDisc::Stats::GetNDroppedBytes (std::string reason) const
{
uint64_t count = 0;
auto it = nDroppedBytesBeforeEnqueue.find (reason);
if (it != nDroppedBytesBeforeEnqueue.end ())
{
count += it->second;
}
it = nDroppedBytesAfterDequeue.find (reason);
if (it != nDroppedBytesAfterDequeue.end ())
{
count += it->second;
}
return count;
}
uint32_t
QueueDisc::Stats::GetNMarkedPackets (std::string reason) const
{
auto it = nMarkedPackets.find (reason);
if (it != nMarkedPackets.end ())
{
return it->second;
}
return 0;
}
uint64_t
QueueDisc::Stats::GetNMarkedBytes (std::string reason) const
{
auto it = nMarkedBytes.find (reason);
if (it != nMarkedBytes.end ())
{
return it->second;
}
return 0;
}
void
QueueDisc::Stats::Print (std::ostream &os) const
{
std::map<std::string, uint32_t>::const_iterator itp;
std::map<std::string, uint64_t>::const_iterator itb;
os << std::endl << "Packets/Bytes received: "
<< nTotalReceivedPackets << " / "
<< nTotalReceivedBytes
@@ -127,14 +200,59 @@ QueueDisc::Stats::Print (std::ostream &os) const
<< nTotalDroppedBytes
<< std::endl << "Packets/Bytes dropped before enqueue: "
<< nTotalDroppedPacketsBeforeEnqueue << " / "
<< nTotalDroppedBytesBeforeEnqueue
<< std::endl << "Packets/Bytes dropped after dequeue: "
<< nTotalDroppedBytesBeforeEnqueue;
itp = nDroppedPacketsBeforeEnqueue.begin ();
itb = nDroppedBytesBeforeEnqueue.begin ();
while (itp != nDroppedPacketsBeforeEnqueue.end () &&
itb != nDroppedBytesBeforeEnqueue.end ())
{
NS_ASSERT (itp->first.compare (itb->first) == 0);
os << std::endl << " " << itp->first << ": "
<< itp->second << " / " << itb->second;
itp++;
itb++;
}
os << std::endl << "Packets/Bytes dropped after dequeue: "
<< nTotalDroppedPacketsAfterDequeue << " / "
<< nTotalDroppedBytesAfterDequeue
<< std::endl << "Packets/Bytes sent: "
<< nTotalDroppedBytesAfterDequeue;
itp = nDroppedPacketsAfterDequeue.begin ();
itb = nDroppedBytesAfterDequeue.begin ();
while (itp != nDroppedPacketsAfterDequeue.end () &&
itb != nDroppedBytesAfterDequeue.end ())
{
NS_ASSERT (itp->first.compare (itb->first) == 0);
os << std::endl << " " << itp->first << ": "
<< itp->second << " / " << itb->second;
itp++;
itb++;
}
os << std::endl << "Packets/Bytes sent: "
<< nTotalSentPackets << " / "
<< nTotalSentBytes
<< std::endl;
<< std::endl << "Packets/Bytes marked: "
<< nTotalMarkedPackets << " / "
<< nTotalMarkedBytes;
itp = nMarkedPackets.begin ();
itb = nMarkedBytes.begin ();
while (itp != nMarkedPackets.end () &&
itb != nMarkedBytes.end ())
{
NS_ASSERT (itp->first.compare (itb->first) == 0);
os << std::endl << " " << itp->first << ": "
<< itp->second << " / " << itb->second;
itp++;
itb++;
}
os << std::endl;
}
std::ostream & operator << (std::ostream &os, const QueueDisc::Stats &stats)
@@ -185,6 +303,9 @@ TypeId QueueDisc::GetTypeId (void)
.AddTraceSource ("DropAfterDequeue", "Drop a packet after dequeue",
MakeTraceSourceAccessor (&QueueDisc::m_traceDropAfterDequeue),
"ns3::QueueDiscItem::TracedCallback")
.AddTraceSource ("Mark", "Mark a packet stored in the queue disc",
MakeTraceSourceAccessor (&QueueDisc::m_traceMark),
"ns3::QueueDiscItem::TracedCallback")
.AddTraceSource ("PacketsInQueue",
"Number of packets currently stored in the queue disc",
MakeTraceSourceAccessor (&QueueDisc::m_nPackets),
@@ -208,6 +329,51 @@ QueueDisc::QueueDisc ()
m_running (false)
{
NS_LOG_FUNCTION (this);
using namespace std::placeholders;
// Remove ambiguity for overloaded member functions
typedef std::basic_string<char>& (std::basic_string<char>::*Function) (const char*);
Function append = &std::basic_string<char>::append,
assign = &std::basic_string<char>::assign;
// The operator() of these function objects calls the QueueDisc::DropBeforeEnqueue
// and QueueDisc::DropAfterDequeue methods of this QueueDisc object (these function
// objects are bound to this QueueDisc object), which require two arguments: a
// Ptr<const QueueDiscItem> and a const char*. Given that a callback to the operator()
// is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the Queue
// class, the first argument is provided by such traces, while the second argument
// (the reason why the packet was dropped) is bound to the INTERNAL_QUEUE_DROP constant.
m_internalQueueDbeFunctor = std::bind (&QueueDisc::DropBeforeEnqueue, this,
_1, (const char*)INTERNAL_QUEUE_DROP);
m_internalQueueDadFunctor = std::bind (&QueueDisc::DropAfterDequeue, this,
_1, (const char*)INTERNAL_QUEUE_DROP);
// The operator() of these function objects calls the QueueDisc::DropBeforeEnqueue
// and QueueDisc::DropAfterDequeue methods of this QueueDisc object (these function
// objects are bound to this QueueDisc object), which require two arguments: a
// Ptr<const QueueDiscItem> and a const char*. Given that a callback to the operator()
// is connected to the DropBeforeEnqueue and DropAfterDequeue traces of the QueueDisc
// class, both arguments are provided by such traces. The first argument is provided
// as is, while the second argument (the reason why the packet was dropped) is obtained
// by calling m_childQueueDiscDropMsg.assign (CHILD_QUEUE_DISC_DROP).append (_2).data ()
// i.e., the second argument is the concatenation of the CHILD_QUEUE_DISC_DROP constant
// and the second argument provided by the traces of the QueueDisc class.
m_childQueueDiscDbeFunctor = std::bind (&QueueDisc::DropBeforeEnqueue, this, _1,
std::bind (&std::basic_string<char>::data,
std::bind (append,
std::bind (assign,
&m_childQueueDiscDropMsg,
(const char*)CHILD_QUEUE_DISC_DROP),
_2)));
m_childQueueDiscDadFunctor = std::bind (&QueueDisc::DropAfterDequeue, this, _1,
std::bind (&std::basic_string<char>::data,
std::bind (append,
std::bind (assign,
&m_childQueueDiscDropMsg,
(const char*)CHILD_QUEUE_DISC_DROP),
_2)));
}
QueueDisc::~QueueDisc ()
@@ -320,6 +486,7 @@ void
QueueDisc::AddInternalQueue (Ptr<InternalQueue> queue)
{
NS_LOG_FUNCTION (this);
// set various callbacks on the internal queue, so that the queue disc is
// notified of packets enqueued, dequeued or dropped by the internal queue
queue->TraceConnectWithoutContext ("Enqueue",
@@ -327,9 +494,11 @@ QueueDisc::AddInternalQueue (Ptr<InternalQueue> queue)
queue->TraceConnectWithoutContext ("Dequeue",
MakeCallback (&QueueDisc::PacketDequeued, this));
queue->TraceConnectWithoutContext ("DropBeforeEnqueue",
MakeCallback (&QueueDisc::DropBeforeEnqueue, this));
MakeCallback (&InternalQueueDropFunctor::operator(),
&m_internalQueueDbeFunctor));
queue->TraceConnectWithoutContext ("DropAfterDequeue",
MakeCallback (&QueueDisc::DropAfterDequeue, this));
MakeCallback (&InternalQueueDropFunctor::operator(),
&m_internalQueueDadFunctor));
m_queues.push_back (queue);
}
@@ -375,6 +544,7 @@ QueueDisc::AddQueueDiscClass (Ptr<QueueDiscClass> qdClass)
// such queue discs do not implement the enqueue/dequeue methods
NS_ABORT_MSG_IF (qdClass->GetQueueDisc ()->GetWakeMode () == WAKE_CHILD,
"A queue disc with WAKE_CHILD as wake mode can only be a root queue disc");
// set the parent callbacks on the child queue disc, so that it can notify
// the parent queue disc of packets enqueued, dequeued or dropped
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Enqueue",
@@ -382,9 +552,11 @@ QueueDisc::AddQueueDiscClass (Ptr<QueueDiscClass> qdClass)
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Dequeue",
MakeCallback (&QueueDisc::PacketDequeued, this));
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropBeforeEnqueue",
MakeCallback (&QueueDisc::DropBeforeEnqueue, this));
MakeCallback (&ChildQueueDiscDropFunctor::operator(),
&m_childQueueDiscDbeFunctor));
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropAfterDequeue",
MakeCallback (&QueueDisc::DropAfterDequeue, this));
MakeCallback (&ChildQueueDiscDropFunctor::operator(),
&m_childQueueDiscDadFunctor));
m_classes.push_back (qdClass);
}
@@ -448,33 +620,124 @@ QueueDisc::PacketDequeued (Ptr<const QueueDiscItem> item)
}
void
QueueDisc::DropBeforeEnqueue (Ptr<const QueueDiscItem> item)
QueueDisc::DropBeforeEnqueue (Ptr<const QueueDiscItem> item, const char* reason)
{
NS_LOG_FUNCTION (this << item);
NS_LOG_FUNCTION (this << item << reason);
m_stats.nTotalDroppedPackets++;
m_stats.nTotalDroppedBytes += item->GetSize ();
m_stats.nTotalDroppedPacketsBeforeEnqueue++;
m_stats.nTotalDroppedBytesBeforeEnqueue += item->GetSize ();
// update the number of packets dropped for the given reason
std::map<std::string, uint32_t>::iterator itp = m_stats.nDroppedPacketsBeforeEnqueue.find (reason);
if (itp != m_stats.nDroppedPacketsBeforeEnqueue.end ())
{
itp->second++;
}
else
{
m_stats.nDroppedPacketsBeforeEnqueue[reason] = 1;
}
// update the amount of bytes dropped for the given reason
std::map<std::string, uint64_t>::iterator itb = m_stats.nDroppedBytesBeforeEnqueue.find (reason);
if (itb != m_stats.nDroppedBytesBeforeEnqueue.end ())
{
itb->second += item->GetSize ();
}
else
{
m_stats.nDroppedBytesBeforeEnqueue[reason] = item->GetSize ();
}
NS_LOG_DEBUG ("Total packets/bytes dropped before enqueue: "
<< m_stats.nTotalDroppedPacketsBeforeEnqueue << " / "
<< m_stats.nTotalDroppedBytesBeforeEnqueue);
NS_LOG_LOGIC ("m_traceDropBeforeEnqueue (p)");
m_traceDrop (item);
m_traceDropBeforeEnqueue (item);
m_traceDropBeforeEnqueue (item, reason);
}
void
QueueDisc::DropAfterDequeue (Ptr<const QueueDiscItem> item)
QueueDisc::DropAfterDequeue (Ptr<const QueueDiscItem> item, const char* reason)
{
NS_LOG_FUNCTION (this << item);
NS_LOG_FUNCTION (this << item << reason);
m_stats.nTotalDroppedPackets++;
m_stats.nTotalDroppedBytes += item->GetSize ();
m_stats.nTotalDroppedPacketsAfterDequeue++;
m_stats.nTotalDroppedBytesAfterDequeue += item->GetSize ();
// update the number of packets dropped for the given reason
std::map<std::string, uint32_t>::iterator itp = m_stats.nDroppedPacketsAfterDequeue.find (reason);
if (itp != m_stats.nDroppedPacketsAfterDequeue.end ())
{
itp->second++;
}
else
{
m_stats.nDroppedPacketsAfterDequeue[reason] = 1;
}
// update the amount of bytes dropped for the given reason
std::map<std::string, uint64_t>::iterator itb = m_stats.nDroppedBytesAfterDequeue.find (reason);
if (itb != m_stats.nDroppedBytesAfterDequeue.end ())
{
itb->second += item->GetSize ();
}
else
{
m_stats.nDroppedBytesAfterDequeue[reason] = item->GetSize ();
}
NS_LOG_DEBUG ("Total packets/bytes dropped after dequeue: "
<< m_stats.nTotalDroppedPacketsAfterDequeue << " / "
<< m_stats.nTotalDroppedBytesAfterDequeue);
NS_LOG_LOGIC ("m_traceDropAfterDequeue (p)");
m_traceDrop (item);
m_traceDropAfterDequeue (item);
m_traceDropAfterDequeue (item, reason);
}
bool
QueueDisc::Mark (Ptr<QueueDiscItem> item, const char* reason)
{
NS_LOG_FUNCTION (this << item << reason);
bool retval = item->Mark ();
if (!retval)
{
return false;
}
m_stats.nTotalMarkedPackets++;
m_stats.nTotalMarkedBytes += item->GetSize ();
// update the number of packets marked for the given reason
std::map<std::string, uint32_t>::iterator itp = m_stats.nMarkedPackets.find (reason);
if (itp != m_stats.nMarkedPackets.end ())
{
itp->second++;
}
else
{
m_stats.nMarkedPackets[reason] = 1;
}
// update the amount of bytes marked for the given reason
std::map<std::string, uint64_t>::iterator itb = m_stats.nMarkedBytes.find (reason);
if (itb != m_stats.nMarkedBytes.end ())
{
itb->second += item->GetSize ();
}
else
{
m_stats.nMarkedBytes[reason] = item->GetSize ();
}
NS_LOG_DEBUG ("Total packets/bytes marked: "
<< m_stats.nTotalMarkedPackets << " / "
<< m_stats.nTotalMarkedBytes);
m_traceMark (item, reason);
return true;
}
bool

View File

@@ -25,6 +25,9 @@
#include "ns3/net-device.h"
#include "ns3/queue-item.h"
#include <vector>
#include <map>
#include <functional>
#include <string>
#include "packet-filter.h"
namespace ns3 {
@@ -129,6 +132,12 @@ private:
* - queued = enqueued - dequeued
* - sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
*
* Separate counters are also kept for each possible reason to drop a packet.
* When a packet is dropped by an internal queue, e.g., because the queue is full,
* the reason is "Dropped by internal queue". When a packet is dropped by a child
* queue disc, the reason is "(Dropped by child queue disc) " followed by the
* reason why the child queue disc dropped the packet.
*
* The QueueDisc base class provides the SojournTime trace source, which provides
* the sojourn time of every packet dequeued from a queue disc, including packets
* that are dropped or requeued after being dequeued. The sojourn time is taken
@@ -165,22 +174,62 @@ public:
uint32_t nTotalDroppedPackets;
/// Total packets dropped before enqueue
uint32_t nTotalDroppedPacketsBeforeEnqueue;
/// Packets dropped before enqueue, for each reason
std::map<std::string, uint32_t> nDroppedPacketsBeforeEnqueue;
/// Total packets dropped after dequeue
uint32_t nTotalDroppedPacketsAfterDequeue;
/// Packets dropped after dequeue, for each reason
std::map<std::string, uint32_t> nDroppedPacketsAfterDequeue;
/// Total dropped bytes
uint64_t nTotalDroppedBytes;
/// Total bytes dropped before enqueue
uint64_t nTotalDroppedBytesBeforeEnqueue;
/// Bytes dropped before enqueue, for each reason
std::map<std::string, uint64_t> nDroppedBytesBeforeEnqueue;
/// Total bytes dropped after dequeue
uint64_t nTotalDroppedBytesAfterDequeue;
/// Bytes dropped after dequeue, for each reason
std::map<std::string, uint64_t> nDroppedBytesAfterDequeue;
/// Total requeued packets
uint32_t nTotalRequeuedPackets;
/// Total requeued bytes
uint64_t nTotalRequeuedBytes;
/// Total marked packets
uint32_t nTotalMarkedPackets;
/// Marked packets, for each reason
std::map<std::string, uint32_t> nMarkedPackets;
/// Total marked bytes
uint32_t nTotalMarkedBytes;
/// Marked bytes, for each reason
std::map<std::string, uint64_t> nMarkedBytes;
/// constructor
Stats ();
/**
* \brief Get the number of packets dropped for the given reason
* \param reason the reason why packets were dropped
* \return the number of packets dropped for the given reason
*/
uint32_t GetNDroppedPackets (std::string reason) const;
/**
* \brief Get the amount of bytes dropped for the given reason
* \param reason the reason why packets were dropped
* \return the amount of bytes dropped for the given reason
*/
uint64_t GetNDroppedBytes (std::string reason) const;
/**
* \brief Get the number of packets marked for the given reason
* \param reason the reason why packets were marked
* \return the number of packets marked for the given reason
*/
uint32_t GetNMarkedPackets (std::string reason) const;
/**
* \brief Get the amount of bytes marked for the given reason
* \param reason the reason why packets were marked
* \return the amount of bytes marked for the given reason
*/
uint64_t GetNMarkedBytes (std::string reason) const;
/**
* \brief Print the statistics.
* \param os output stream in which the data should be printed.
@@ -369,6 +418,10 @@ public:
*/
virtual WakeMode GetWakeMode (void) const;
// Reasons for dropping packets
static constexpr const char* INTERNAL_QUEUE_DROP = "Dropped by internal queue"; //!< Packet dropped by an internal queue
static constexpr const char* CHILD_QUEUE_DISC_DROP = "(Dropped by child queue disc) "; //!< Packet dropped by a child queue disc
protected:
/**
* \brief Dispose of the object
@@ -388,19 +441,30 @@ protected:
* \brief Perform the actions required when the queue disc is notified of
* a packet dropped before enqueue
* \param item item that was dropped
* This method must be called by subclasses to notify parent (this class) of a packet
* dropped before enqueue
* \param reason the reason why the item was dropped
* This method must be called by subclasses to record that a packet was
* dropped before enqueue for the specified reason
*/
void DropBeforeEnqueue (Ptr<const QueueDiscItem> item);
void DropBeforeEnqueue (Ptr<const QueueDiscItem> item, const char* reason);
/**
* \brief Perform the actions required when the queue disc is notified of
* a packet dropped after dequeue
* \param item item that was dropped
* This method must be called by subclasses to notify parent (this class) of a packet
* dropped after dequeue
* \param reason the reason why the item was dropped
* This method must be called by subclasses to record that a packet was
* dropped after dequeue for the specified reason
*/
void DropAfterDequeue (Ptr<const QueueDiscItem> item);
void DropAfterDequeue (Ptr<const QueueDiscItem> item, const char* reason);
/**
* \brief Marks the given packet and, if successful, updates the counters
* associated with the given reason
* \param item item that has to be marked
* \param reason the reason why the item has to be marked
* \return true if the item was successfully marked, false otherwise
*/
bool Mark (Ptr<QueueDiscItem> item, const char* reason);
private:
/**
@@ -523,19 +587,36 @@ private:
Ptr<NetDeviceQueueInterface> m_devQueueIface; //!< NetDevice queue interface
bool m_running; //!< The queue disc is performing multiple dequeue operations
Ptr<QueueDiscItem> m_requeued; //!< The last packet that failed to be transmitted
std::string m_childQueueDiscDropMsg; //!< Reason why a packet was dropped by a child queue disc
/// Traced callback: fired when a packet is enqueued
TracedCallback<Ptr<const QueueDiscItem> > m_traceEnqueue;
/// Traced callback: fired when a packet is dequeued
/// Traced callback: fired when a packet is dequeued
TracedCallback<Ptr<const QueueDiscItem> > m_traceDequeue;
/// Traced callback: fired when a packet is requeued
TracedCallback<Ptr<const QueueDiscItem> > m_traceRequeue;
/// Traced callback: fired when a packet is dropped
TracedCallback<Ptr<const QueueDiscItem> > m_traceDrop;
/// Traced callback: fired when a packet is dropped before enqueue
TracedCallback<Ptr<const QueueDiscItem> > m_traceDropBeforeEnqueue;
TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceDropBeforeEnqueue;
/// Traced callback: fired when a packet is dropped after dequeue
TracedCallback<Ptr<const QueueDiscItem> > m_traceDropAfterDequeue;
TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceDropAfterDequeue;
/// Traced callback: fired when a packet is marked
TracedCallback<Ptr<const QueueDiscItem>, const char* > m_traceMark;
/// Type for the function objects notifying that a packet has been dropped by an internal queue
typedef std::function<void (Ptr<const QueueDiscItem>)> InternalQueueDropFunctor;
/// Type for the function objects notifying that a packet has been dropped by a child queue disc
typedef std::function<void (Ptr<const QueueDiscItem>, const char*)> ChildQueueDiscDropFunctor;
/// Function object called when an internal queue dropped a packet before enqueue
InternalQueueDropFunctor m_internalQueueDbeFunctor;
/// Function object called when an internal queue dropped a packet after dequeue
InternalQueueDropFunctor m_internalQueueDadFunctor;
/// Function object called when a child queue disc dropped a packet before enqueue
ChildQueueDiscDropFunctor m_childQueueDiscDbeFunctor;
/// Function object called when a child queue disc dropped a packet after dequeue
ChildQueueDiscDropFunctor m_childQueueDiscDadFunctor;
};
/**

View File

@@ -355,13 +355,6 @@ RedQueueDisc::SetTh (double minTh, double maxTh)
m_maxTh = maxTh;
}
RedQueueDisc::Stats
RedQueueDisc::GetStats ()
{
NS_LOG_FUNCTION (this);
return m_stats;
}
int64_t
RedQueueDisc::AssignStreams (int64_t stream)
{
@@ -453,23 +446,20 @@ RedQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
if (dropType == DTYPE_UNFORCED)
{
if (!m_useEcn || !item->Mark ())
if (!m_useEcn || !Mark (item, UNFORCED_MARK))
{
NS_LOG_DEBUG ("\t Dropping due to Prob Mark " << m_qAvg);
m_stats.unforcedDrop++;
DropBeforeEnqueue (item);
DropBeforeEnqueue (item, UNFORCED_DROP);
return false;
}
NS_LOG_DEBUG ("\t Marking due to Prob Mark " << m_qAvg);
m_stats.unforcedMark++;
}
else if (dropType == DTYPE_FORCED)
{
if (m_useHardDrop || !m_useEcn || !item->Mark ())
if (m_useHardDrop || !m_useEcn || !Mark (item, FORCED_MARK))
{
NS_LOG_DEBUG ("\t Dropping due to Hard Mark " << m_qAvg);
m_stats.forcedDrop++;
DropBeforeEnqueue (item);
DropBeforeEnqueue (item, FORCED_DROP);
if (m_isNs1Compat)
{
m_count = 0;
@@ -478,16 +468,10 @@ RedQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
return false;
}
NS_LOG_DEBUG ("\t Marking due to Hard Mark " << m_qAvg);
m_stats.forcedMark++;
}
bool retval = GetInternalQueue (0)->Enqueue (item);
if (!retval)
{
m_stats.qLimDrop++;
}
// If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the
// internal queue because QueueDisc::AddInternalQueue sets the trace callback
@@ -550,11 +534,6 @@ RedQueueDisc::InitializeParams (void)
}
NS_ASSERT (m_minTh <= m_maxTh);
m_stats.forcedDrop = 0;
m_stats.unforcedDrop = 0;
m_stats.qLimDrop = 0;
m_stats.forcedMark = 0;
m_stats.unforcedMark = 0;
m_qAvg = 0.0;
m_count = 0;

View File

@@ -108,18 +108,6 @@ public:
Below, //!< When m_qAvg < m_minTh
};
/**
* \brief Stats
*/
typedef struct
{
uint32_t unforcedDrop; //!< Early probability drops
uint32_t forcedDrop; //!< Forced drops, m_qAvg > m_maxTh
uint32_t qLimDrop; //!< Drops due to queue limits
uint32_t unforcedMark; //!< Early probability marks
uint32_t forcedMark; //!< Forced marks, m_qAvg > m_maxTh
} Stats;
/**
* \brief Drop types
*/
@@ -232,13 +220,6 @@ public:
*/
void SetTh (double minTh, double maxTh);
/**
* \brief Get the RED statistics after running.
*
* \returns The drop statistics.
*/
Stats GetStats ();
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
@@ -249,6 +230,13 @@ public:
*/
int64_t AssignStreams (int64_t stream);
// Reasons for dropping packets
static constexpr const char* UNFORCED_DROP = "Unforced drop"; //!< Early probability drops
static constexpr const char* FORCED_DROP = "Forced drop"; //!< Forced drops, m_qAvg > m_maxTh
// Reasons for marking packets
static constexpr const char* UNFORCED_MARK = "Unforced mark"; //!< Early probability marks
static constexpr const char* FORCED_MARK = "Forced mark"; //!< Forced marks, m_qAvg > m_maxTh
protected:
/**
* \brief Dispose of the object
@@ -309,8 +297,6 @@ private:
*/
double ModifyP (double p, uint32_t size);
Stats m_stats; //!< RED statistics
// ** Variables supplied by user
QueueDiscMode m_mode; //!< Mode (Bytes or packets)
uint32_t m_meanPktSize; //!< Avg pkt size

View File

@@ -163,8 +163,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute QW");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops");
QueueDisc::Stats st = queue->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be zero unforced drops");
// test 2: Verify automatic setting of QW. [QW = 0.0 with lesser LinkBandwidth]
@@ -183,8 +184,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute LinkBandwidth");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
st = queue->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
// test 3: Verify automatic setting of QW. [QW = -1.0 with default LinkBandwidth]
@@ -201,8 +203,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute QW");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops");
st = queue->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be zero unforced drops");
// test 4: Verify automatic setting of QW. [QW = -1.0 with lesser LinkBandwidth]
@@ -221,8 +224,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute LinkBandwidth");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
st = queue->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
// test 5: Verify automatic setting of QW. [QW = -2.0 with default LinkBandwidth]
@@ -239,8 +243,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute QW");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
uint32_t test5 = st.unforcedDrop;
st = queue->GetStats ();
uint32_t test5 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_NE (test5, 0, "There should be some unforced drops");
@@ -260,8 +264,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute LinkBandwidth");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
uint32_t test6 = st.unforcedDrop;
st = queue->GetStats ();
uint32_t test6 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_NE (test6, test5, "Test 6 should have more unforced drops than Test 5");
@@ -277,8 +281,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute QueueLimit");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
st = queue->GetStats ();
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
// test 8: Verify automatic setting of minTh and maxTh. [minTh = maxTh = 0.0, with higher LinkBandwidth]
@@ -295,8 +300,9 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
"Verify that we can actually set the attribute LinkBandwidth");
queue->Initialize ();
Enqueue (queue, pktSize, 300);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be zero unforced drops");
st = queue->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be zero unforced drops");
// test 9: Default RED (automatic and adaptive settings disabled)
@@ -319,9 +325,10 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
EnqueueWithDelay (queue, pktSize, 300);
Simulator::Stop (Seconds (5));
Simulator::Run ();
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
uint32_t test9 = st.unforcedDrop;
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
st = queue->GetStats ();
uint32_t test9 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
// test 10: Adaptive RED (automatic and adaptive settings enabled)
@@ -338,8 +345,8 @@ AredQueueDiscTestCase::RunAredDiscTest (StringValue mode)
EnqueueWithDelay (queue, pktSize, 300);
Simulator::Stop (Seconds (5));
Simulator::Run ();
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
uint32_t test10 = st.unforcedDrop;
st = queue->GetStats ();
uint32_t test10 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_LT (test10, test9, "Test 10 should have less unforced drops than test 9");
}

View File

@@ -211,7 +211,8 @@ CoDelQueueDiscBasicEnqueueDequeue::DoRun (void)
queue->Enqueue (Create<CodelQueueDiscTestItem> (p6, dest, 0));
QueueTestSize (queue, 6 * modeSize, "There should be six packets in queue");
NS_TEST_EXPECT_MSG_EQ (queue->GetDropOverLimit (), 0, "There should be no packets being dropped due to full queue");
NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::OVERLIMIT_DROP),
0, "There should be no packets being dropped due to full queue");
Ptr<QueueDiscItem> item;
@@ -248,7 +249,8 @@ CoDelQueueDiscBasicEnqueueDequeue::DoRun (void)
item = queue->Dequeue ();
NS_TEST_EXPECT_MSG_EQ ((item == 0), true, "There are really no packets in queue");
NS_TEST_EXPECT_MSG_EQ (queue->GetDropCount (), 0, "There should be no packet drops according to CoDel algorithm");
NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP), 0,
"There should be no packet drops according to CoDel algorithm");
}
/**
@@ -346,7 +348,8 @@ CoDelQueueDiscBasicOverflow::DoRun (void)
queue->Enqueue (Create<CodelQueueDiscTestItem> (p3, dest, 0));
QueueTestSize (queue, 500 * modeSize, "There should be 500 packets in queue");
NS_TEST_EXPECT_MSG_EQ (queue->GetDropOverLimit (), 3, "There should be three packets being dropped due to full queue");
NS_TEST_EXPECT_MSG_EQ (queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::OVERLIMIT_DROP),
3, "There should be three packets being dropped due to full queue");
}
void
@@ -590,7 +593,7 @@ CoDelQueueDiscBasicDrop::Enqueue (Ptr<CoDelQueueDisc> queue, uint32_t size, uint
void
CoDelQueueDiscBasicDrop::Dequeue (Ptr<CoDelQueueDisc> queue, uint32_t modeSize)
{
uint32_t initialDropCount = queue->GetDropCount ();
uint32_t initialDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP);
uint32_t initialQSize = queue->GetQueueSize ();
uint32_t initialDropNext = queue->GetDropNext ();
Time currentTime = Simulator::Now ();
@@ -608,7 +611,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr<CoDelQueueDisc> queue, uint32_t modeSize)
{
if (currentTime < queue->GetInterval ())
{
currentDropCount = queue->GetDropCount ();
currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP);
NS_TEST_EXPECT_MSG_EQ (currentDropCount, 0, "We are not in dropping state."
"Sojourn time has just gone above target from below."
"Hence, there should be no packet drops");
@@ -617,7 +620,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr<CoDelQueueDisc> queue, uint32_t modeSize)
}
else if (currentTime >= queue->GetInterval ())
{
currentDropCount = queue->GetDropCount ();
currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP);
QueueTestSize (queue, initialQSize - 2 * modeSize, "Sojourn time has been above target for at least interval."
"We enter the dropping state, perform initial packet drop, and dequeue the next."
"So there should be 2 more packets dequeued.");
@@ -628,7 +631,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr<CoDelQueueDisc> queue, uint32_t modeSize)
{ // In dropping state
if (currentTime.GetMicroSeconds () < initialDropNext)
{
currentDropCount = queue->GetDropCount ();
currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP);
QueueTestSize (queue, initialQSize - modeSize, "We are in dropping state."
"Sojourn is still above target."
"However, it's not time for next drop."
@@ -638,7 +641,7 @@ CoDelQueueDiscBasicDrop::Dequeue (Ptr<CoDelQueueDisc> queue, uint32_t modeSize)
}
else if (currentTime.GetMicroSeconds () >= initialDropNext)
{
currentDropCount = queue->GetDropCount ();
currentDropCount = queue->GetStats ().GetNDroppedPackets (CoDelQueueDisc::TARGET_EXCEEDED_DROP);
QueueTestSize (queue, initialQSize - (m_dropNextCount + 1) * modeSize, "We are in dropping state."
"It's time for next drop."
"The number of packets dequeued equals to the number of times m_dropNext is updated plus initial dequeue");

View File

@@ -245,10 +245,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode)
DequeueWithDelay (queue, 0.012, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
PieQueueDisc::Stats st = StaticCast<PieQueueDisc> (queue)->GetStats ();
uint32_t test2 = st.unforcedDrop;
QueueDisc::Stats st = queue->GetStats ();
uint32_t test2 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_NE (test2, 0, "There should be some unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
// test 3: same as test 2, but with higher QueueDelayReference
@@ -276,10 +276,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode)
DequeueWithDelay (queue, 0.012, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
st = StaticCast<PieQueueDisc> (queue)->GetStats ();
uint32_t test3 = st.unforcedDrop;
st = queue->GetStats ();
uint32_t test3 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_LT (test3, test2, "Test 3 should have less unforced drops than test 2");
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
// test 4: same as test 2, but with reduced dequeue rate
@@ -307,10 +307,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode)
DequeueWithDelay (queue, 0.015, 400); // delay between two successive dequeue events is increased
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
st = StaticCast<PieQueueDisc> (queue)->GetStats ();
uint32_t test4 = st.unforcedDrop;
st = queue->GetStats ();
uint32_t test4 = st.GetNDroppedPackets (PieQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_GT (test4, test2, "Test 4 should have more unforced drops than test 2");
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should be zero forced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
// test 5: same dequeue rate as test 4, but with higher Tupdate
@@ -338,10 +338,10 @@ PieQueueDiscTestCase::RunPieTest (StringValue mode)
DequeueWithDelay (queue, 0.015, 400);
Simulator::Stop (Seconds (8.0));
Simulator::Run ();
st = StaticCast<PieQueueDisc> (queue)->GetStats ();
uint32_t test5 = st.unforcedDrop;
st = queue->GetStats ();
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.forcedDrop, 0, "There should be zero forced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (PieQueueDisc::FORCED_DROP), 0, "There should be zero forced drops");
}
void

View File

@@ -225,10 +225,13 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute QueueLimit");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
RedQueueDisc::Stats st = StaticCast<RedQueueDisc> (queue)->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should zero dropped packets due probability mark");
NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should zero dropped packets due hardmark mark");
NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should zero dropped packets due queue full");
QueueDisc::Stats st = queue->GetStats ();
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be zero unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP), 0,
"There should be zero forced dropps");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP), 0,
"There should be zero drops due to queue limit");
// save number of drops from tests
struct d {
@@ -257,8 +260,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute QW");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test3 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
st = queue->GetStats ();
drop.test3 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
+ st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
+ st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
NS_TEST_EXPECT_MSG_NE (drop.test3, 0, "There should be some dropped packets");
@@ -277,8 +282,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute QW");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test4 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
st = queue->GetStats ();
drop.test4 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
+ st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
+ st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
NS_TEST_EXPECT_MSG_GT (drop.test4, drop.test3, "Test 4 should have more drops than test 3");
@@ -299,8 +306,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute LInterm");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test5 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
st = queue->GetStats ();
drop.test5 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
+ st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
+ st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
NS_TEST_EXPECT_MSG_GT (drop.test5, drop.test3, "Test 5 should have more drops than test 3");
@@ -320,8 +329,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute Gentle");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test6 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
st = queue->GetStats ();
drop.test6 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
+ st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
+ st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
NS_TEST_EXPECT_MSG_GT (drop.test6, drop.test3, "Test 6 should have more drops than test 3");
@@ -341,8 +352,10 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute Wait");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test7 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
st = queue->GetStats ();
drop.test7 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP)
+ st.GetNDroppedPackets (RedQueueDisc::FORCED_DROP)
+ st.GetNDroppedPackets (QueueDisc::INTERNAL_QUEUE_DROP);
NS_TEST_EXPECT_MSG_GT (drop.test7, drop.test3, "Test 7 should have more drops than test 3");
@@ -368,10 +381,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute UseECN");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
st = queue->GetStats ();
// Packets are not ECN capable, so there should be only unforced drops, no unforced marks
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.unforcedMark, 0, "There should be no unforced marks");
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
"There should be no unforced marks");
// test 9: Packets are ECN capable, but RED queue disc is not ECN enabled
@@ -394,10 +409,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute UseECN");
queue->Initialize ();
Enqueue (queue, pktSize, 300, true);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
st = queue->GetStats ();
// RED queue disc is not ECN enabled, so there should be only unforced drops, no unforced marks
NS_TEST_EXPECT_MSG_NE (st.unforcedDrop, 0, "There should be some unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.unforcedMark, 0, "There should be no unforced marks");
NS_TEST_EXPECT_MSG_NE (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be some unforced drops");
NS_TEST_EXPECT_MSG_EQ (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
"There should be no unforced marks");
// test 10: Packets are ECN capable and RED queue disc is ECN enabled
@@ -420,10 +437,12 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute UseECN");
queue->Initialize ();
Enqueue (queue, pktSize, 300, true);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
st = queue->GetStats ();
// Packets are ECN capable, RED queue disc is ECN enabled; there should be only unforced marks, no unforced drops
NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should be no unforced drops");
NS_TEST_EXPECT_MSG_NE (st.unforcedMark, 0, "There should be some unforced marks");
NS_TEST_EXPECT_MSG_EQ (st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP), 0,
"There should be no unforced drops");
NS_TEST_EXPECT_MSG_NE (st.GetNMarkedPackets (RedQueueDisc::UNFORCED_MARK), 0,
"There should be some unforced marks");
// test 11: RED with default parameter settings, linear drop probability and fixed m_curMaxP
@@ -446,8 +465,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute Gentle");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test11 = st.unforcedDrop;
st = queue->GetStats ();
drop.test11 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_NE (drop.test11, 0, "There should some dropped packets due to probability mark");
@@ -471,8 +490,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute FengAdaptive");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test12 = st.unforcedDrop;
st = queue->GetStats ();
drop.test12 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_LT (drop.test12, drop.test11, "Test 12 should have less drops due to probability mark than test 11");
@@ -498,8 +517,8 @@ RedQueueDiscTestCase::RunRedTest (StringValue mode)
"Verify that we can actually set the attribute NLRED");
queue->Initialize ();
Enqueue (queue, pktSize, 300, false);
st = StaticCast<RedQueueDisc> (queue)->GetStats ();
drop.test13 = st.unforcedDrop;
st = queue->GetStats ();
drop.test13 = st.GetNDroppedPackets (RedQueueDisc::UNFORCED_DROP);
NS_TEST_EXPECT_MSG_LT (drop.test13, drop.test11, "Test 13 should have less drops due to probability mark than test 11");
}