traffic-control: (fixes #2751) Ensure queue discs keep correct statistics
This commit is contained in:
@@ -95,6 +95,14 @@ 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.
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Changes to existing API:</h2>
|
||||
<ul>
|
||||
|
||||
@@ -107,6 +107,7 @@ Bugs fixed
|
||||
- Bug 2733 - Ideal wifi manager cannot handle NSS higher than 1
|
||||
- Bug 2741 - IPv4 fragmentation fails when last fragment have to be re-fragmented.
|
||||
- Bug 2744 - 802.11n/ac with RTS/CTS is crashing for a large number of nodes
|
||||
- Bug 2751 - QueueDisc::Enqueue() order of operations
|
||||
- Bug 2757 - 802.11n/ac/ax maximum TXOP is not properly enforced
|
||||
- Bug 2758 - IPv4 sockets bound to unicast receive also subnet-directed broadcasts
|
||||
- Bug 2759 - Packets sent to broadcast address are converted to subnet-directed broadcast
|
||||
|
||||
@@ -170,11 +170,11 @@ main (int argc, char *argv[])
|
||||
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flowmon.GetClassifier ());
|
||||
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats ();
|
||||
std::cout << std::endl << "*** Flow monitor statistics ***" << std::endl;
|
||||
std::cout << " Tx Packets: " << stats[1].txPackets << std::endl;
|
||||
std::cout << " Tx Bytes: " << stats[1].txBytes << std::endl;
|
||||
std::cout << " Tx Packets/Bytes: " << stats[1].txPackets
|
||||
<< " / " << stats[1].txBytes << std::endl;
|
||||
std::cout << " Offered Load: " << stats[1].txBytes * 8.0 / (stats[1].timeLastTxPacket.GetSeconds () - stats[1].timeFirstTxPacket.GetSeconds ()) / 1000000 << " Mbps" << std::endl;
|
||||
std::cout << " Rx Packets: " << stats[1].rxPackets << std::endl;
|
||||
std::cout << " Rx Bytes: " << stats[1].rxBytes << std::endl;
|
||||
std::cout << " Rx Packets/Bytes: " << stats[1].rxPackets
|
||||
<< " / " << stats[1].rxBytes << std::endl;
|
||||
uint32_t packetsDroppedByQueueDisc = 0;
|
||||
uint64_t bytesDroppedByQueueDisc = 0;
|
||||
if (stats[1].packetsDropped.size () > Ipv4FlowProbe::DROP_QUEUE_DISC)
|
||||
@@ -182,8 +182,8 @@ main (int argc, char *argv[])
|
||||
packetsDroppedByQueueDisc = stats[1].packetsDropped[Ipv4FlowProbe::DROP_QUEUE_DISC];
|
||||
bytesDroppedByQueueDisc = stats[1].bytesDropped[Ipv4FlowProbe::DROP_QUEUE_DISC];
|
||||
}
|
||||
std::cout << " Packets Dropped by Queue Disc: " << packetsDroppedByQueueDisc << std::endl;
|
||||
std::cout << " Bytes Dropped by Queue Disc: " << bytesDroppedByQueueDisc << std::endl;
|
||||
std::cout << " Packets/Bytes Dropped by Queue Disc: " << packetsDroppedByQueueDisc
|
||||
<< " / " << bytesDroppedByQueueDisc << std::endl;
|
||||
uint32_t packetsDroppedByNetDevice = 0;
|
||||
uint64_t bytesDroppedByNetDevice = 0;
|
||||
if (stats[1].packetsDropped.size () > Ipv4FlowProbe::DROP_QUEUE)
|
||||
@@ -191,8 +191,8 @@ main (int argc, char *argv[])
|
||||
packetsDroppedByNetDevice = stats[1].packetsDropped[Ipv4FlowProbe::DROP_QUEUE];
|
||||
bytesDroppedByNetDevice = stats[1].bytesDropped[Ipv4FlowProbe::DROP_QUEUE];
|
||||
}
|
||||
std::cout << " Packets Dropped by NetDevice: " << packetsDroppedByNetDevice << std::endl;
|
||||
std::cout << " Bytes Dropped by NetDevice: " << bytesDroppedByNetDevice << std::endl;
|
||||
std::cout << " Packets/Bytes Dropped by NetDevice: " << packetsDroppedByNetDevice
|
||||
<< " / " << bytesDroppedByNetDevice << std::endl;
|
||||
std::cout << " Throughput: " << stats[1].rxBytes * 8.0 / (stats[1].timeLastRxPacket.GetSeconds () - stats[1].timeFirstRxPacket.GetSeconds ()) / 1000000 << " Mbps" << std::endl;
|
||||
std::cout << " Mean delay: " << stats[1].delaySum.GetSeconds () / stats[1].rxPackets << std::endl;
|
||||
std::cout << " Mean jitter: " << stats[1].jitterSum.GetSeconds () / (stats[1].rxPackets - 1) << std::endl;
|
||||
@@ -212,10 +212,6 @@ main (int argc, char *argv[])
|
||||
std::cout << " Rx Bytes: " << totalPacketsThr << std::endl;
|
||||
std::cout << " Average Goodput: " << thr << " Mbit/s" << std::endl;
|
||||
std::cout << std::endl << "*** TC Layer statistics ***" << std::endl;
|
||||
std::cout << " Packets dropped by the TC layer: " << q->GetTotalDroppedPackets () << std::endl;
|
||||
std::cout << " Bytes dropped by the TC layer: " << q->GetTotalDroppedBytes () << std::endl;
|
||||
std::cout << " Packets dropped by the netdevice: " << queue->GetTotalDroppedPackets () << std::endl;
|
||||
std::cout << " Packets requeued by the TC layer: " << q->GetTotalRequeuedPackets () << std::endl;
|
||||
|
||||
std::cout << q->GetStats () << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -552,6 +552,10 @@ Queue<Item>::DoRemove (ConstIterator pos)
|
||||
m_nBytes -= item->GetSize ();
|
||||
m_nPackets--;
|
||||
|
||||
// packets are first dequeued and then dropped
|
||||
NS_LOG_LOGIC ("m_traceDequeue (p)");
|
||||
m_traceDequeue (item);
|
||||
|
||||
DropAfterDequeue (item);
|
||||
}
|
||||
return item;
|
||||
|
||||
@@ -50,10 +50,26 @@ queue disc and within the device.
|
||||
The traffic control layer interacts with a queue disc in a simple manner: after requesting
|
||||
to enqueue a packet, the traffic control layer requests the qdisc to "run", i.e., to
|
||||
dequeue a set of packets, until a predefined number ("quota") of packets is dequeued
|
||||
or the netdevice stops the queue disc. A netdevice may stop the queue disc when its
|
||||
transmission queue(s) is/are (almost) full. Also, a netdevice may wake the
|
||||
queue disc when its transmission queue(s) is/are (almost) empty. Waking a queue disc
|
||||
is equivalent to make it run.
|
||||
or the netdevice stops the queue disc. A netdevice shall
|
||||
stop the queue disc when its transmission queue does not have room for another
|
||||
packet. Also, a netdevice shall wake the queue disc when it detects that there
|
||||
is room for another packet in its transmission queue, but the transmission queue
|
||||
is stopped. Waking a queue disc is equivalent to make it run.
|
||||
|
||||
Every queue disc collects statistics about the total number of packets/bytes
|
||||
received from the upper layers (in case of root queue disc) or from the parent
|
||||
queue disc (in case of child queue disc), enqueued, dequeued, requeued, dropped,
|
||||
dropped before enqueue, dropped after dequeue, stored in the queue disc and
|
||||
sent to the netdevice or to the parent queue disc. Note that packets that are
|
||||
dequeued may be requeued, i.e., retained by the traffic control infrastructure,
|
||||
if the netdevice is not ready to receive them. Requeued packets are not part
|
||||
of the queue disc. The following identities hold:
|
||||
|
||||
* dropped = dropped before enqueue + dropped after dequeue
|
||||
* received = dropped before enqueue + enqueued
|
||||
* queued = enqueued - dequeued
|
||||
* sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
|
||||
|
||||
|
||||
Design
|
||||
==========
|
||||
|
||||
@@ -281,7 +281,7 @@ CoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
if (m_mode == QUEUE_DISC_MODE_PACKETS && (GetInternalQueue (0)->GetNPackets () + 1 > m_maxPackets))
|
||||
{
|
||||
NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
++m_dropOverLimit;
|
||||
return false;
|
||||
}
|
||||
@@ -289,7 +289,7 @@ CoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
if (m_mode == QUEUE_DISC_MODE_BYTES && (GetInternalQueue (0)->GetNBytes () + item->GetSize () > m_maxBytes))
|
||||
{
|
||||
NS_LOG_LOGIC ("Queue full (packet would exceed max bytes) -- droppping pkt");
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
++m_dropOverLimit;
|
||||
return false;
|
||||
}
|
||||
@@ -300,8 +300,8 @@ CoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
|
||||
bool retval = GetInternalQueue (0)->Enqueue (item);
|
||||
|
||||
// If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue
|
||||
// because QueueDisc::AddInternalQueue sets the drop callback
|
||||
// If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the
|
||||
// internal queue because QueueDisc::AddInternalQueue sets the trace callback
|
||||
|
||||
NS_LOG_LOGIC ("Number packets " << GetInternalQueue (0)->GetNPackets ());
|
||||
NS_LOG_LOGIC ("Number bytes " << GetInternalQueue (0)->GetNBytes ());
|
||||
@@ -400,7 +400,7 @@ 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);
|
||||
Drop (item);
|
||||
DropAfterDequeue (item);
|
||||
|
||||
++m_dropCount;
|
||||
++m_count;
|
||||
@@ -440,7 +440,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;
|
||||
Drop (item);
|
||||
DropAfterDequeue (item);
|
||||
|
||||
item = GetInternalQueue (0)->Dequeue ();
|
||||
|
||||
|
||||
@@ -162,7 +162,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.");
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,10 +65,10 @@ PfifoFastQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
if (GetNPackets () > m_limit)
|
||||
if (GetNPackets () >= m_limit)
|
||||
{
|
||||
NS_LOG_LOGIC ("Queue disc limit exceeded -- dropping packet");
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ PfifoFastQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
|
||||
bool retval = GetInternalQueue (band)->Enqueue (item);
|
||||
|
||||
// If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue
|
||||
// because QueueDisc::AddInternalQueue sets the drop callback
|
||||
// If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the
|
||||
// internal queue because QueueDisc::AddInternalQueue sets the trace callback
|
||||
|
||||
NS_LOG_LOGIC ("Number packets band " << band << ": " << GetInternalQueue (band)->GetNPackets ());
|
||||
|
||||
|
||||
@@ -197,14 +197,14 @@ PieQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
|| (GetMode () == QUEUE_DISC_MODE_BYTES && nQueued + item->GetSize () > m_queueLimit))
|
||||
{
|
||||
// Drops due to queue limit: reactive
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
m_stats.forcedDrop++;
|
||||
return false;
|
||||
}
|
||||
else if (DropEarly (item, nQueued))
|
||||
{
|
||||
// Early probability drop: proactive
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
m_stats.unforcedDrop++;
|
||||
return false;
|
||||
}
|
||||
@@ -212,8 +212,8 @@ PieQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
// No drop
|
||||
bool retval = GetInternalQueue (0)->Enqueue (item);
|
||||
|
||||
// If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue
|
||||
// because QueueDisc::AddInternalQueue sets the drop callback
|
||||
// If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the
|
||||
// internal queue because QueueDisc::AddInternalQueue sets the trace callback
|
||||
|
||||
NS_LOG_LOGIC ("\t bytesInQueue " << GetInternalQueue (0)->GetNBytes ());
|
||||
NS_LOG_LOGIC ("\t packetsInQueue " << GetInternalQueue (0)->GetNPackets ());
|
||||
|
||||
@@ -86,6 +86,61 @@ QueueDiscClass::SetQueueDisc (Ptr<QueueDisc> qd)
|
||||
m_queueDisc = qd;
|
||||
}
|
||||
|
||||
QueueDisc::Stats::Stats ()
|
||||
: nTotalReceivedPackets (0),
|
||||
nTotalReceivedBytes (0),
|
||||
nTotalSentPackets (0),
|
||||
nTotalSentBytes (0),
|
||||
nTotalEnqueuedPackets (0),
|
||||
nTotalEnqueuedBytes (0),
|
||||
nTotalDequeuedPackets (0),
|
||||
nTotalDequeuedBytes (0),
|
||||
nTotalDroppedPackets (0),
|
||||
nTotalDroppedPacketsBeforeEnqueue (0),
|
||||
nTotalDroppedPacketsAfterDequeue (0),
|
||||
nTotalDroppedBytes (0),
|
||||
nTotalDroppedBytesBeforeEnqueue (0),
|
||||
nTotalDroppedBytesAfterDequeue (0),
|
||||
nTotalRequeuedPackets (0),
|
||||
nTotalRequeuedBytes (0)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::Stats::Print (std::ostream &os) const
|
||||
{
|
||||
os << std::endl << "Packets/Bytes received: "
|
||||
<< nTotalReceivedPackets << " / "
|
||||
<< nTotalReceivedBytes
|
||||
<< std::endl << "Packets/Bytes enqueued: "
|
||||
<< nTotalEnqueuedPackets << " / "
|
||||
<< nTotalEnqueuedBytes
|
||||
<< std::endl << "Packets/Bytes dequeued: "
|
||||
<< nTotalDequeuedPackets << " / "
|
||||
<< nTotalDequeuedBytes
|
||||
<< std::endl << "Packets/Bytes requeued: "
|
||||
<< nTotalRequeuedPackets << " / "
|
||||
<< nTotalRequeuedBytes
|
||||
<< std::endl << "Packets/Bytes dropped: "
|
||||
<< nTotalDroppedPackets << " / "
|
||||
<< nTotalDroppedBytes
|
||||
<< std::endl << "Packets/Bytes dropped before enqueue: "
|
||||
<< nTotalDroppedPacketsBeforeEnqueue << " / "
|
||||
<< nTotalDroppedBytesBeforeEnqueue
|
||||
<< std::endl << "Packets/Bytes dropped after dequeue: "
|
||||
<< nTotalDroppedPacketsAfterDequeue << " / "
|
||||
<< nTotalDroppedBytesAfterDequeue
|
||||
<< std::endl << "Packets/Bytes sent: "
|
||||
<< nTotalSentPackets << " / "
|
||||
<< nTotalSentBytes
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream &os, const QueueDisc::Stats &stats)
|
||||
{
|
||||
stats.Print (os);
|
||||
return os;
|
||||
}
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (QueueDisc);
|
||||
|
||||
@@ -123,6 +178,12 @@ TypeId QueueDisc::GetTypeId (void)
|
||||
.AddTraceSource ("Drop", "Drop a packet stored in the queue disc",
|
||||
MakeTraceSourceAccessor (&QueueDisc::m_traceDrop),
|
||||
"ns3::QueueDiscItem::TracedCallback")
|
||||
.AddTraceSource ("DropBeforeEnqueue", "Drop a packet before enqueue",
|
||||
MakeTraceSourceAccessor (&QueueDisc::m_traceDropBeforeEnqueue),
|
||||
"ns3::QueueDiscItem::TracedCallback")
|
||||
.AddTraceSource ("DropAfterDequeue", "Drop a packet after dequeue",
|
||||
MakeTraceSourceAccessor (&QueueDisc::m_traceDropAfterDequeue),
|
||||
"ns3::QueueDiscItem::TracedCallback")
|
||||
.AddTraceSource ("PacketsInQueue",
|
||||
"Number of packets currently stored in the queue disc",
|
||||
MakeTraceSourceAccessor (&QueueDisc::m_nPackets),
|
||||
@@ -138,12 +199,6 @@ TypeId QueueDisc::GetTypeId (void)
|
||||
QueueDisc::QueueDisc ()
|
||||
: m_nPackets (0),
|
||||
m_nBytes (0),
|
||||
m_nTotalReceivedPackets (0),
|
||||
m_nTotalReceivedBytes (0),
|
||||
m_nTotalDroppedPackets (0),
|
||||
m_nTotalDroppedBytes (0),
|
||||
m_nTotalRequeuedPackets (0),
|
||||
m_nTotalRequeuedBytes (0),
|
||||
m_running (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
@@ -194,6 +249,25 @@ QueueDisc::DoInitialize (void)
|
||||
Object::DoInitialize ();
|
||||
}
|
||||
|
||||
const QueueDisc::Stats&
|
||||
QueueDisc::GetStats (void)
|
||||
{
|
||||
NS_ASSERT (m_stats.nTotalDroppedPackets == m_stats.nTotalDroppedPacketsBeforeEnqueue
|
||||
+ m_stats.nTotalDroppedPacketsAfterDequeue);
|
||||
NS_ASSERT (m_stats.nTotalDroppedBytes == m_stats.nTotalDroppedBytesBeforeEnqueue
|
||||
+ m_stats.nTotalDroppedBytesAfterDequeue);
|
||||
|
||||
// the total number of sent packets is only updated here to avoid to increase it
|
||||
// after a dequeue and then having to decrease it if the packet is dropped after
|
||||
// dequeue or requeued
|
||||
m_stats.nTotalSentPackets = m_stats.nTotalDequeuedPackets - (m_requeued ? 1 : 0)
|
||||
- m_stats.nTotalDroppedPacketsAfterDequeue;
|
||||
m_stats.nTotalSentBytes = m_stats.nTotalDequeuedBytes - (m_requeued ? m_requeued->GetSize () : 0)
|
||||
- m_stats.nTotalDroppedBytesAfterDequeue;
|
||||
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc::GetNPackets () const
|
||||
{
|
||||
@@ -208,48 +282,6 @@ QueueDisc::GetNBytes (void) const
|
||||
return m_nBytes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc::GetTotalReceivedPackets (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalReceivedPackets;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc::GetTotalReceivedBytes (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalReceivedBytes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc::GetTotalDroppedPackets (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalDroppedPackets;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc:: GetTotalDroppedBytes (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalDroppedBytes;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc::GetTotalRequeuedPackets (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalRequeuedPackets;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
QueueDisc:: GetTotalRequeuedBytes (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_nTotalRequeuedBytes;
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::SetNetDevice (Ptr<NetDevice> device)
|
||||
{
|
||||
@@ -282,9 +314,16 @@ void
|
||||
QueueDisc::AddInternalQueue (Ptr<InternalQueue> queue)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
// set the drop callback on the internal queue, so that the queue disc is
|
||||
// notified of packets dropped by the internal queue
|
||||
queue->TraceConnectWithoutContext ("Drop", MakeCallback (&QueueDisc::Drop, 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",
|
||||
MakeCallback (&QueueDisc::PacketEnqueued, this));
|
||||
queue->TraceConnectWithoutContext ("Dequeue",
|
||||
MakeCallback (&QueueDisc::PacketDequeued, this));
|
||||
queue->TraceConnectWithoutContext ("DropBeforeEnqueue",
|
||||
MakeCallback (&QueueDisc::DropBeforeEnqueue, this));
|
||||
queue->TraceConnectWithoutContext ("DropAfterDequeue",
|
||||
MakeCallback (&QueueDisc::DropAfterDequeue, this));
|
||||
m_queues.push_back (queue);
|
||||
}
|
||||
|
||||
@@ -330,9 +369,16 @@ 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 drop callback on the child queue disc, so that it can notify
|
||||
// packet drops to the parent queue disc
|
||||
qdClass->GetQueueDisc ()->SetParentDropCallback (MakeCallback (&QueueDisc::Drop, this));
|
||||
// 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",
|
||||
MakeCallback (&QueueDisc::PacketEnqueued, this));
|
||||
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("Dequeue",
|
||||
MakeCallback (&QueueDisc::PacketDequeued, this));
|
||||
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropBeforeEnqueue",
|
||||
MakeCallback (&QueueDisc::DropBeforeEnqueue, this));
|
||||
qdClass->GetQueueDisc ()->TraceConnectWithoutContext ("DropAfterDequeue",
|
||||
MakeCallback (&QueueDisc::DropAfterDequeue, this));
|
||||
m_classes.push_back (qdClass);
|
||||
}
|
||||
|
||||
@@ -370,49 +416,57 @@ QueueDisc::GetWakeMode (void) const
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::SetParentDropCallback (ParentDropCallback cb)
|
||||
QueueDisc::PacketEnqueued (Ptr<const QueueDiscItem> item)
|
||||
{
|
||||
m_parentDropCallback = cb;
|
||||
m_nPackets++;
|
||||
m_nBytes += item->GetSize ();
|
||||
m_stats.nTotalEnqueuedPackets++;
|
||||
m_stats.nTotalEnqueuedBytes += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceEnqueue (p)");
|
||||
m_traceEnqueue (item);
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::Drop (Ptr<const QueueDiscItem> item)
|
||||
QueueDisc::PacketDequeued (Ptr<const QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
// if the wake mode of this queue disc is WAKE_CHILD, packets are directly
|
||||
// enqueued/dequeued from the child queue discs, thus this queue disc does not
|
||||
// keep valid packets/bytes counters and no actions need to be performed.
|
||||
if (this->GetWakeMode () == WAKE_CHILD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG (m_nPackets >= 1u, "No packet in the queue disc, cannot drop");
|
||||
NS_ASSERT_MSG (m_nBytes >= item->GetSize (), "The size of the packet that"
|
||||
<< " is reported to be dropped is greater than the amount of bytes"
|
||||
<< "stored in the queue disc");
|
||||
|
||||
m_nPackets--;
|
||||
m_nBytes -= item->GetSize ();
|
||||
m_nTotalDroppedPackets++;
|
||||
m_nTotalDroppedBytes += item->GetSize ();
|
||||
m_stats.nTotalDequeuedPackets++;
|
||||
m_stats.nTotalDequeuedBytes += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceDrop (p)");
|
||||
m_traceDrop (item);
|
||||
|
||||
NotifyParentDrop (item);
|
||||
NS_LOG_LOGIC ("m_traceDequeue (p)");
|
||||
m_traceDequeue (item);
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::NotifyParentDrop (Ptr<const QueueDiscItem> item)
|
||||
QueueDisc::DropBeforeEnqueue (Ptr<const QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
// the parent drop callback is clearly null on root queue discs
|
||||
if (!m_parentDropCallback.IsNull ())
|
||||
{
|
||||
m_parentDropCallback (item);
|
||||
}
|
||||
|
||||
m_stats.nTotalDroppedPackets++;
|
||||
m_stats.nTotalDroppedBytes += item->GetSize ();
|
||||
m_stats.nTotalDroppedPacketsBeforeEnqueue++;
|
||||
m_stats.nTotalDroppedBytesBeforeEnqueue += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceDropBeforeEnqueue (p)");
|
||||
m_traceDrop (item);
|
||||
m_traceDropBeforeEnqueue (item);
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::DropAfterDequeue (Ptr<const QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
m_stats.nTotalDroppedPackets++;
|
||||
m_stats.nTotalDroppedBytes += item->GetSize ();
|
||||
m_stats.nTotalDroppedPacketsAfterDequeue++;
|
||||
m_stats.nTotalDroppedBytesAfterDequeue += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceDropAfterDequeue (p)");
|
||||
m_traceDrop (item);
|
||||
m_traceDropAfterDequeue (item);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -420,15 +474,29 @@ QueueDisc::Enqueue (Ptr<QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << item);
|
||||
|
||||
m_nPackets++;
|
||||
m_nBytes += item->GetSize ();
|
||||
m_nTotalReceivedPackets++;
|
||||
m_nTotalReceivedBytes += item->GetSize ();
|
||||
m_stats.nTotalReceivedPackets++;
|
||||
m_stats.nTotalReceivedBytes += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceEnqueue (p)");
|
||||
m_traceEnqueue (item);
|
||||
bool retval = DoEnqueue (item);
|
||||
|
||||
return DoEnqueue (item);
|
||||
// DoEnqueue may return false because:
|
||||
// 1) the internal queue is full
|
||||
// -> the DropBeforeEnqueue method of this queue disc is automatically called
|
||||
// because QueueDisc::AddInternalQueue sets the trace callback
|
||||
// 2) the child queue disc dropped the packet
|
||||
// -> the DropBeforeEnqueue method of this queue disc is automatically called
|
||||
// because QueueDisc::AddQueueDiscClass sets the trace callback
|
||||
// 3) it dropped the packet
|
||||
// -> DoEnqueue has to explicitly call DropBeforeEnqueue
|
||||
// Thus, we do not have to call DropBeforeEnqueue here.
|
||||
|
||||
// check that the received packet was either enqueued or dropped
|
||||
NS_ASSERT (m_stats.nTotalReceivedPackets == m_stats.nTotalDroppedPacketsBeforeEnqueue +
|
||||
m_stats.nTotalEnqueuedPackets);
|
||||
NS_ASSERT (m_stats.nTotalReceivedBytes == m_stats.nTotalDroppedBytesBeforeEnqueue +
|
||||
m_stats.nTotalEnqueuedBytes);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Ptr<QueueDiscItem>
|
||||
@@ -436,17 +504,10 @@ QueueDisc::Dequeue (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Ptr<QueueDiscItem> item;
|
||||
item = DoDequeue ();
|
||||
Ptr<QueueDiscItem> item = DoDequeue ();
|
||||
|
||||
if (item != 0)
|
||||
{
|
||||
m_nPackets--;
|
||||
m_nBytes -= item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceDequeue (p)");
|
||||
m_traceDequeue (item);
|
||||
}
|
||||
NS_ASSERT (m_nPackets == m_stats.nTotalEnqueuedPackets - m_stats.nTotalDequeuedPackets);
|
||||
NS_ASSERT (m_nBytes == m_stats.nTotalEnqueuedBytes - m_stats.nTotalDequeuedBytes);
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -530,12 +591,6 @@ QueueDisc::DequeuePacket ()
|
||||
{
|
||||
item = m_requeued;
|
||||
m_requeued = 0;
|
||||
|
||||
m_nPackets--;
|
||||
m_nBytes -= item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceDequeue (p)");
|
||||
m_traceDequeue (item);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -566,10 +621,8 @@ QueueDisc::Requeue (Ptr<QueueDiscItem> item)
|
||||
m_requeued = item;
|
||||
/// \todo netif_schedule (q);
|
||||
|
||||
m_nPackets++; // it's still part of the queue
|
||||
m_nBytes += item->GetSize ();
|
||||
m_nTotalRequeuedPackets++;
|
||||
m_nTotalRequeuedBytes += item->GetSize ();
|
||||
m_stats.nTotalRequeuedPackets++;
|
||||
m_stats.nTotalRequeuedBytes += item->GetSize ();
|
||||
|
||||
NS_LOG_LOGIC ("m_traceRequeue (p)");
|
||||
m_traceRequeue (item);
|
||||
|
||||
@@ -107,19 +107,80 @@ private:
|
||||
* An attempt is made, also, to enqueue each packet in the "same" queue both within the
|
||||
* queue disc and within the device.
|
||||
*
|
||||
* The traffic control layer interacts with a queue disc in a simple manner: after requesting
|
||||
* to enqueue a packet, the traffic control layer requests the qdisc to "run", i.e., to
|
||||
* dequeue a set of packets, until a predefined number ("quota") of packets is dequeued
|
||||
* or the netdevice stops the queue disc. A netdevice may stop the queue disc when its
|
||||
* transmission queue(s) is/are (almost) full. Also, a netdevice may wake the
|
||||
* queue disc when its transmission queue(s) is/are (almost) empty. Waking a queue disc
|
||||
* is equivalent to make it run.
|
||||
* The traffic control layer interacts with a queue disc in a simple manner: after
|
||||
* requesting to enqueue a packet, the traffic control layer requests the qdisc to
|
||||
* "run", i.e., to dequeue a set of packets, until a predefined number ("quota")
|
||||
* of packets is dequeued or the netdevice stops the queue disc. A netdevice shall
|
||||
* stop the queue disc when its transmission queue does not have room for another
|
||||
* packet. Also, a netdevice shall wake the queue disc when it detects that there
|
||||
* is room for another packet in its transmission queue, but the transmission queue
|
||||
* is stopped. Waking a queue disc is equivalent to make it run.
|
||||
*
|
||||
* Every queue disc collects statistics about the total number of packets/bytes
|
||||
* received from the upper layers (in case of root queue disc) or from the parent
|
||||
* queue disc (in case of child queue disc), enqueued, dequeued, requeued, dropped,
|
||||
* dropped before enqueue, dropped after dequeue, queued in the queue disc and
|
||||
* sent to the netdevice or to the parent queue disc. Note that packets that are
|
||||
* dequeued may be requeued, i.e., retained by the traffic control infrastructure,
|
||||
* if the netdevice is not ready to receive them. Requeued packets are not part
|
||||
* of the queue disc. The following identities hold:
|
||||
* - dropped = dropped before enqueue + dropped after dequeue
|
||||
* - received = dropped before enqueue + enqueued
|
||||
* - queued = enqueued - dequeued
|
||||
* - sent = dequeued - dropped after dequeue (- 1 if there is a requeued packet)
|
||||
*
|
||||
* The design and implementation of this class is heavily inspired by Linux.
|
||||
* For more details, see the traffic-control model page.
|
||||
*/
|
||||
class QueueDisc : public Object {
|
||||
public:
|
||||
|
||||
/// \brief Structure that keeps the queue disc statistics
|
||||
struct Stats
|
||||
{
|
||||
/// Total received packets
|
||||
uint32_t nTotalReceivedPackets;
|
||||
/// Total received bytes
|
||||
uint64_t nTotalReceivedBytes;
|
||||
/// Total sent packets -- this value is not kept up to date, call GetStats first
|
||||
uint32_t nTotalSentPackets;
|
||||
/// Total sent bytes -- this value is not kept up to date, call GetStats first
|
||||
uint64_t nTotalSentBytes;
|
||||
/// Total enqueued packets
|
||||
uint32_t nTotalEnqueuedPackets;
|
||||
/// Total enqueued bytes
|
||||
uint64_t nTotalEnqueuedBytes;
|
||||
/// Total dequeued packets
|
||||
uint32_t nTotalDequeuedPackets;
|
||||
/// Total dequeued bytes
|
||||
uint64_t nTotalDequeuedBytes;
|
||||
/// Total dropped packets
|
||||
uint32_t nTotalDroppedPackets;
|
||||
/// Total packets dropped before enqueue
|
||||
uint32_t nTotalDroppedPacketsBeforeEnqueue;
|
||||
/// Total packets dropped after dequeue
|
||||
uint32_t nTotalDroppedPacketsAfterDequeue;
|
||||
/// Total dropped bytes
|
||||
uint64_t nTotalDroppedBytes;
|
||||
/// Total bytes dropped before enqueue
|
||||
uint64_t nTotalDroppedBytesBeforeEnqueue;
|
||||
/// Total bytes dropped after dequeue
|
||||
uint64_t nTotalDroppedBytesAfterDequeue;
|
||||
/// Total requeued packets
|
||||
uint32_t nTotalRequeuedPackets;
|
||||
/// Total requeued bytes
|
||||
uint64_t nTotalRequeuedBytes;
|
||||
|
||||
/// constructor
|
||||
Stats ();
|
||||
|
||||
/**
|
||||
* \brief Print the statistics.
|
||||
* \param os output stream in which the data should be printed.
|
||||
*/
|
||||
void Print (std::ostream &os) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
@@ -133,12 +194,7 @@ public:
|
||||
* \brief Get the number of packets stored by the queue disc
|
||||
* \return the number of packets stored by the queue disc.
|
||||
*
|
||||
* Note that the number of packets stored by the queue disc is updated as soon
|
||||
* as a packet is received by the queue disc and before actually enqueuing the
|
||||
* packet (i.e., before calling DoEnqueue). Thus, while implementing the DoEnqueue
|
||||
* method of a subclass, keep in mind that GetNPackets returns the number of
|
||||
* packets stored in the queue disc, including the packet that we are trying
|
||||
* to enqueue.
|
||||
* The requeued packet, if any, is counted.
|
||||
*/
|
||||
uint32_t GetNPackets (void) const;
|
||||
|
||||
@@ -146,50 +202,15 @@ public:
|
||||
* \brief Get the amount of bytes stored by the queue disc
|
||||
* \return the amount of bytes stored by the queue disc.
|
||||
*
|
||||
* Note that the amount of bytes stored by the queue disc is updated as soon
|
||||
* as a packet is received by the queue disc and before actually enqueuing the
|
||||
* packet (i.e., before calling DoEnqueue). Thus, while implementing the DoEnqueue
|
||||
* method of a subclass, keep in mind that GetNBytes returns the amount of
|
||||
* bytes stored in the queue disc, including the size of the packet that we are
|
||||
* trying to enqueue.
|
||||
* The requeued packet, if any, is counted.
|
||||
*/
|
||||
uint32_t GetNBytes (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total number of received packets
|
||||
* \return the total number of received packets.
|
||||
* \brief Retrieve all the collected statistics.
|
||||
* \return the collected statistics.
|
||||
*/
|
||||
uint32_t GetTotalReceivedPackets (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total amount of received bytes
|
||||
* \return the total amount of received bytes.
|
||||
*/
|
||||
uint32_t GetTotalReceivedBytes (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total number of dropped packets
|
||||
* \return the total number of dropped packets.
|
||||
*/
|
||||
uint32_t GetTotalDroppedPackets (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total amount of dropped bytes
|
||||
* \return the total amount of dropped bytes.
|
||||
*/
|
||||
uint32_t GetTotalDroppedBytes (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total number of requeued packets
|
||||
* \return the total number of requeued packets.
|
||||
*/
|
||||
uint32_t GetTotalRequeuedPackets (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the total amount of requeued bytes
|
||||
* \return the total amount of requeued bytes.
|
||||
*/
|
||||
uint32_t GetTotalRequeuedBytes (void) const;
|
||||
const Stats& GetStats (void);
|
||||
|
||||
/**
|
||||
* \brief Set the NetDevice on which this queue discipline is installed.
|
||||
@@ -341,18 +362,6 @@ public:
|
||||
*/
|
||||
virtual WakeMode GetWakeMode (void) const;
|
||||
|
||||
/// Callback invoked by a child queue disc to notify the parent of a packet drop
|
||||
typedef Callback<void, Ptr<const QueueDiscItem> > ParentDropCallback;
|
||||
|
||||
/**
|
||||
* \brief Set the parent drop callback
|
||||
* \param cb the callback to set
|
||||
*
|
||||
* Called when a queue disc class is added to a queue disc in order to set a
|
||||
* callback to the Drop method of the parent queue disc.
|
||||
*/
|
||||
virtual void SetParentDropCallback (ParentDropCallback cb);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Dispose of the object
|
||||
@@ -369,11 +378,22 @@ protected:
|
||||
void DoInitialize (void);
|
||||
|
||||
/**
|
||||
* \brief Drop a packet
|
||||
* \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 is called by subclasses to notify parent (this class) of packet drops.
|
||||
* This method must be called by subclasses to notify parent (this class) of a packet
|
||||
* dropped before enqueue
|
||||
*/
|
||||
void Drop (Ptr<const QueueDiscItem> item);
|
||||
void DropBeforeEnqueue (Ptr<const QueueDiscItem> item);
|
||||
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
void DropAfterDequeue (Ptr<const QueueDiscItem> item);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -393,12 +413,6 @@ private:
|
||||
*/
|
||||
QueueDisc &operator = (const QueueDisc &o);
|
||||
|
||||
/**
|
||||
* \brief Notify the parent queue disc of a packet drop
|
||||
* \param item item that was dropped
|
||||
*/
|
||||
void NotifyParentDrop (Ptr<const QueueDiscItem> item);
|
||||
|
||||
/**
|
||||
* This function actually enqueues a packet into the queue disc.
|
||||
* \param item item to enqueue
|
||||
@@ -472,6 +486,20 @@ private:
|
||||
*/
|
||||
bool Transmit (Ptr<QueueDiscItem> item);
|
||||
|
||||
/**
|
||||
* \brief Perform the actions required when the queue disc is notified of
|
||||
* a packet enqueue
|
||||
* \param item item that was enqueued
|
||||
*/
|
||||
void PacketEnqueued (Ptr<const QueueDiscItem> item);
|
||||
|
||||
/**
|
||||
* \brief Perform the actions required when the queue disc is notified of
|
||||
* a packet dequeue
|
||||
* \param item item that was dequeued
|
||||
*/
|
||||
void PacketDequeued (Ptr<const QueueDiscItem> item);
|
||||
|
||||
static const uint32_t DEFAULT_QUOTA = 64; //!< Default quota (as in /proc/sys/net/core/dev_weight)
|
||||
|
||||
std::vector<Ptr<InternalQueue> > m_queues; //!< Internal queues
|
||||
@@ -481,29 +509,36 @@ private:
|
||||
TracedValue<uint32_t> m_nPackets; //!< Number of packets in the queue
|
||||
TracedValue<uint32_t> m_nBytes; //!< Number of bytes in the queue
|
||||
|
||||
uint32_t m_nTotalReceivedPackets; //!< Total received packets
|
||||
uint32_t m_nTotalReceivedBytes; //!< Total received bytes
|
||||
uint32_t m_nTotalDroppedPackets; //!< Total dropped packets
|
||||
uint32_t m_nTotalDroppedBytes; //!< Total dropped bytes
|
||||
uint32_t m_nTotalRequeuedPackets; //!< Total requeued packets
|
||||
uint32_t m_nTotalRequeuedBytes; //!< Total requeued bytes
|
||||
Stats m_stats; //!< The collected statistics
|
||||
uint32_t m_quota; //!< Maximum number of packets dequeued in a qdisc run
|
||||
Ptr<NetDevice> m_device; //!< The NetDevice on which this queue discipline is installed
|
||||
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
|
||||
ParentDropCallback m_parentDropCallback; //!< Parent drop callback
|
||||
|
||||
/// Traced callback: fired when a packet is enqueued
|
||||
TracedCallback<Ptr<const QueueDiscItem> > m_traceEnqueue;
|
||||
/// Traced callback: fired when a packet is dequeued
|
||||
TracedCallback<Ptr<const QueueDiscItem> > m_traceDequeue;
|
||||
/// Traced callback: fired when a packet is requeued
|
||||
/// 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;
|
||||
/// Traced callback: fired when a packet is dropped after dequeue
|
||||
TracedCallback<Ptr<const QueueDiscItem> > m_traceDropAfterDequeue;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the stream
|
||||
* \param stats the queue disc statistics
|
||||
* \returns a reference to the stream
|
||||
*/
|
||||
std::ostream& operator<< (std::ostream& os, const QueueDisc::Stats &stats);
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* QueueDisc */
|
||||
|
||||
@@ -457,7 +457,7 @@ RedQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_DEBUG ("\t Dropping due to Prob Mark " << m_qAvg);
|
||||
m_stats.unforcedDrop++;
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
return false;
|
||||
}
|
||||
NS_LOG_DEBUG ("\t Marking due to Prob Mark " << m_qAvg);
|
||||
@@ -469,7 +469,7 @@ RedQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
{
|
||||
NS_LOG_DEBUG ("\t Dropping due to Hard Mark " << m_qAvg);
|
||||
m_stats.forcedDrop++;
|
||||
Drop (item);
|
||||
DropBeforeEnqueue (item);
|
||||
if (m_isNs1Compat)
|
||||
{
|
||||
m_count = 0;
|
||||
@@ -488,8 +488,8 @@ RedQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
|
||||
m_stats.qLimDrop++;
|
||||
}
|
||||
|
||||
// If Queue::Enqueue fails, QueueDisc::Drop is called by the internal queue
|
||||
// because QueueDisc::AddInternalQueue sets the drop callback
|
||||
// If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the
|
||||
// internal queue because QueueDisc::AddInternalQueue sets the trace callback
|
||||
|
||||
NS_LOG_LOGIC ("Number packets " << GetInternalQueue (0)->GetNPackets ());
|
||||
NS_LOG_LOGIC ("Number bytes " << GetInternalQueue (0)->GetNBytes ());
|
||||
|
||||
Reference in New Issue
Block a user