Index: src/point-to-point/model/point-to-point-net-device.cc |
=================================================================== |
--- a/src/point-to-point/model/point-to-point-net-device.cc |
+++ b/src/point-to-point/model/point-to-point-net-device.cc |
@@ -214,6 +214,7 @@ |
m_channel = 0; |
m_receiveErrorModel = 0; |
m_currentPkt = 0; |
+ m_queue = 0; |
NetDevice::DoDispose (); |
} |
@@ -280,18 +281,27 @@ |
m_phyTxEndTrace (m_currentPkt); |
m_currentPkt = 0; |
- Ptr<Packet> p = m_queue->Dequeue (); |
- if (p == 0) |
+ Ptr<NetDeviceQueue> txq = GetTxQueue (0); |
+ |
+ Ptr<QueueItem> item = m_queue->Dequeue (); |
+ if (item == 0) |
{ |
- // |
- // No packet was on the queue, so we just exit. |
- // |
+ NS_LOG_LOGIC ("No pending packets in device queue after tx complete"); |
+ txq->Wake (); |
return; |
} |
// |
- // Got another packet off of the queue, so start the transmit process agin. |
+ // Got another packet off of the queue, so start the transmit process again. |
+ // If the queue was stopped, start it again. Note that we cannot wake the upper |
+ // layers because otherwise a packet is sent to the device while the machine |
+ // state is busy, thus causing the assert in TransmitStart to fail. |
// |
+ if (txq->IsStopped ()) |
+ { |
+ txq->Start (); |
+ } |
+ Ptr<Packet> p = item->GetPacket (); |
m_snifferTrace (p); |
m_promiscSnifferTrace (p); |
TransmitStart (p); |
@@ -510,6 +520,9 @@ |
const Address &dest, |
uint16_t protocolNumber) |
{ |
+ Ptr<NetDeviceQueue> txq = GetTxQueue (0); |
+ NS_ASSERT_MSG (!txq->IsStopped (), "Send should not be called when the device is stopped"); |
+ |
NS_LOG_FUNCTION (this << packet << dest << protocolNumber); |
NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest); |
NS_LOG_LOGIC ("UID is " << packet->GetUid ()); |
@@ -520,7 +533,11 @@ |
// |
if (IsLinkUp () == false) |
{ |
- m_macTxDropTrace (packet); |
+ // Do not fire the drop trace if the packet will be re-queued by the queue disc |
+ if (!IsQueueDiscInstalled ()) |
+ { |
+ m_macTxDropTrace (packet); |
+ } |
return false; |
} |
@@ -535,14 +552,14 @@ |
// |
// We should enqueue and dequeue the packet to hit the tracing hooks. |
// |
- if (m_queue->Enqueue (packet)) |
+ if (m_queue->Enqueue (Create<QueueItem> (packet))) |
{ |
// |
// If the channel is ready for transition we send the packet right now |
// |
if (m_txMachineState == READY) |
{ |
- packet = m_queue->Dequeue (); |
+ packet = m_queue->Dequeue ()->GetPacket (); |
m_snifferTrace (packet); |
m_promiscSnifferTrace (packet); |
return TransmitStart (packet); |
@@ -550,8 +567,14 @@ |
return true; |
} |
- // Enqueue may fail (overflow) |
- m_macTxDropTrace (packet); |
+ // Enqueue may fail (overflow). Stop the tx queue, so that the upper layers |
+ // do not send packets until there is room in the queue again. |
+ txq->Stop (); |
+ // Do not fire the drop trace if the packet will be re-queued by the queue disc |
+ if (!IsQueueDiscInstalled ()) |
+ { |
+ m_macTxDropTrace (packet); |
+ } |
return false; |
} |