From a77e4d39b2147ce5206f7139054ddfc890b78000 Mon Sep 17 00:00:00 2001 From: Greg Steinbrecher Date: Fri, 25 Sep 2020 12:16:53 -0700 Subject: [PATCH] network: (merges !424) Fix instant send in SimpleNetDevice for empty queue Also consolidate scheduling logic into ScheduleTransmit() rather than repeating in both SendFrom() and TransmitComplete() --- src/network/utils/simple-net-device.cc | 57 +++++++++++++++----------- src/network/utils/simple-net-device.h | 8 ++-- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/network/utils/simple-net-device.cc b/src/network/utils/simple-net-device.cc index 9dfc712a0..a8f55f403 100644 --- a/src/network/utils/simple-net-device.cc +++ b/src/network/utils/simple-net-device.cc @@ -446,39 +446,51 @@ SimpleNetDevice::SendFrom (Ptr p, const Address& source, const Address& if (m_queue->Enqueue (p)) { - if (m_queue->GetNPackets () == 1 && !TransmitCompleteEvent.IsRunning ()) + if (m_queue->GetNPackets () == 1 && !FinishTransmissionEvent.IsRunning ()) { - p = m_queue->Dequeue (); - p->RemovePacketTag (tag); - Time txTime = Time (0); - if (m_bps > DataRate (0)) - { - txTime = m_bps.CalculateBytesTxTime (packet->GetSize ()); - } - m_channel->Send (p, protocolNumber, to, from, this); - TransmitCompleteEvent = Simulator::Schedule (txTime, &SimpleNetDevice::TransmitComplete, this); + StartTransmission(); } return true; } - m_channel->Send (packet, protocolNumber, to, from, this); - return true; + return false; } - void -SimpleNetDevice::TransmitComplete () +SimpleNetDevice::StartTransmission () { - NS_LOG_FUNCTION (this); - if (m_queue->GetNPackets () == 0) { return; } - + NS_ASSERT_MSG (!FinishTransmissionEvent.IsRunning (), + "Tried to transmit a packet while another transmission was in progress"); Ptr packet = m_queue->Dequeue (); + /** + * SimpleChannel will deliver the packet to the far end(s) of the link as soon as Send is called + * (or after its fixed delay, if one is configured). So we have to handle the rate of the link here, + * which we do by scheudling FinishTransmission (packetSize / linkRate) time in the future. While + * that event is running, the transmit path of this NetDevice is busy, so we can't send other packets. + * + * SimpleChannel doesn't have a locking mechanism, and doesn't check for collisions, so there's nothing + * we need to do with the channel until the transmisison has "completed" from the perspective of this + * NetDevice. + */ + Time txTime = Time (0); + if (m_bps > DataRate (0)) + { + txTime = m_bps.CalculateBytesTxTime (packet->GetSize ()); + } + FinishTransmissionEvent = Simulator::Schedule (txTime, &SimpleNetDevice::FinishTransmission, this, packet); +} + +void +SimpleNetDevice::FinishTransmission (Ptr packet) +{ + NS_LOG_FUNCTION (this); + SimpleTag tag; packet->RemovePacketTag (tag); @@ -488,12 +500,7 @@ SimpleNetDevice::TransmitComplete () m_channel->Send (packet, proto, dst, src, this); - Time txTime = Time (0); - if (m_bps > DataRate (0)) - { - txTime = m_bps.CalculateBytesTxTime (packet->GetSize ()); - } - TransmitCompleteEvent = Simulator::Schedule (txTime, &SimpleNetDevice::TransmitComplete, this); + StartTransmission(); return; } @@ -535,9 +542,9 @@ SimpleNetDevice::DoDispose (void) m_node = 0; m_receiveErrorModel = 0; m_queue->Flush (); - if (TransmitCompleteEvent.IsRunning ()) + if (FinishTransmissionEvent.IsRunning ()) { - TransmitCompleteEvent.Cancel (); + FinishTransmissionEvent.Cancel (); } NetDevice::DoDispose (); } diff --git a/src/network/utils/simple-net-device.h b/src/network/utils/simple-net-device.h index 480bc1515..49a714f7d 100644 --- a/src/network/utils/simple-net-device.h +++ b/src/network/utils/simple-net-device.h @@ -158,11 +158,13 @@ private: */ TracedCallback > m_phyRxDropTrace; + void StartTransmission(void); + /** - * The TransmitComplete method is used internally to finish the process + * The FinishTransmission method is used internally to finish the process * of sending a packet out on the channel. */ - void TransmitComplete (void); + void FinishTransmission (Ptr packet); bool m_linkUp; //!< Flag indicating whether or not the link is up @@ -174,7 +176,7 @@ private: Ptr > m_queue; //!< The Queue for outgoing packets. DataRate m_bps; //!< The device nominal Data rate. Zero means infinite - EventId TransmitCompleteEvent; //!< the Tx Complete event + EventId FinishTransmissionEvent; //!< the Tx Complete event /** * List of callbacks to fire if the link changes state (up or down).