traffic-control: Record reasons for dropping and marking packets
This commit is contained in:
32
CHANGES.html
32
CHANGES.html
@@ -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
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user