diff --git a/src/point-to-point/model/point-to-point-net-device.cc b/src/point-to-point/model/point-to-point-net-device.cc index bfa31fff6..df7b747ad 100644 --- a/src/point-to-point/model/point-to-point-net-device.cc +++ b/src/point-to-point/model/point-to-point-net-device.cc @@ -206,6 +206,16 @@ PointToPointNetDevice::ProcessHeader (Ptr p, uint16_t& param) return true; } +void +PointToPointNetDevice::DoInitialize (void) +{ + NS_LOG_FUNCTION (this); + // A NetDeviceQueueInterface object must have been aggregated to this device + // by the traffic control layer + m_queueInterface = GetObject (); + NetDevice::DoInitialize (); +} + void PointToPointNetDevice::DoDispose () { @@ -280,18 +290,27 @@ PointToPointNetDevice::TransmitComplete (void) m_phyTxEndTrace (m_currentPkt); m_currentPkt = 0; + NS_ASSERT (m_queueInterface); + Ptr txq = m_queueInterface->GetTxQueue (0); + Ptr 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 p = item->GetPacket (); m_snifferTrace (p); m_promiscSnifferTrace (p); @@ -511,6 +530,11 @@ PointToPointNetDevice::Send ( const Address &dest, uint16_t protocolNumber) { + NS_ASSERT (m_queueInterface); + Ptr txq = m_queueInterface->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 ()); @@ -551,8 +575,10 @@ PointToPointNetDevice::Send ( return true; } - // Enqueue may fail (overflow) + // 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. m_macTxDropTrace (packet); + txq->Stop (); return false; } diff --git a/src/point-to-point/model/point-to-point-net-device.h b/src/point-to-point/model/point-to-point-net-device.h index b43cb2f68..2ec402ce6 100644 --- a/src/point-to-point/model/point-to-point-net-device.h +++ b/src/point-to-point/model/point-to-point-net-device.h @@ -198,6 +198,8 @@ protected: */ void DoMpiReceive (Ptr p); + virtual void DoInitialize (void); + private: /** @@ -435,6 +437,7 @@ private: TracedCallback > m_promiscSnifferTrace; Ptr m_node; //!< Node owning this NetDevice + Ptr m_queueInterface; //!< NetDevice queue interface Mac48Address m_address; //!< Mac48Address of this NetDevice NetDevice::ReceiveCallback m_rxCallback; //!< Receive callback NetDevice::PromiscReceiveCallback m_promiscCallback; //!< Receive callback diff --git a/src/point-to-point/test/point-to-point-test.cc b/src/point-to-point/test/point-to-point-test.cc index 211e6584f..302549b4e 100644 --- a/src/point-to-point/test/point-to-point-test.cc +++ b/src/point-to-point/test/point-to-point-test.cc @@ -86,6 +86,11 @@ PointToPointTest::DoRun (void) a->AddDevice (devA); b->AddDevice (devB); + Ptr ifaceA = CreateObject (); + devA->AggregateObject (ifaceA); + Ptr ifaceB = CreateObject (); + devB->AggregateObject (ifaceB); + Simulator::Schedule (Seconds (1.0), &PointToPointTest::SendOnePacket, this, devA); Simulator::Run ();