wifi: WifiTxTimer can be rescheduled multiple times

This commit is contained in:
Stefano Avallone
2021-10-22 12:33:23 +02:00
committed by Stefano Avallone
parent d7662fbead
commit 91fa037246
2 changed files with 50 additions and 18 deletions

View File

@@ -30,15 +30,17 @@ namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("WifiTxTimer");
WifiTxTimer::WifiTxTimer ()
: m_reason (NOT_RUNNING),
m_rescheduled (false)
: m_timeoutEvent (),
m_reason (NOT_RUNNING),
m_impl (nullptr),
m_end (Seconds (0))
{
}
WifiTxTimer::~WifiTxTimer ()
{
m_timeoutEvent.Cancel ();
m_endRxEvent = 0;
m_impl = 0;
}
void
@@ -46,13 +48,38 @@ WifiTxTimer::Reschedule (const Time& delay)
{
NS_LOG_FUNCTION (this << delay);
if (m_timeoutEvent.IsRunning () && !m_rescheduled)
if (m_timeoutEvent.IsRunning ())
{
NS_LOG_DEBUG ("Rescheduling " << GetReasonString (m_reason) << " timeout in "
<< delay.As (Time::US));
m_timeoutEvent.Cancel ();
m_timeoutEvent = Simulator::Schedule (delay, m_endRxEvent);
m_rescheduled = true;
Time end = Simulator::Now () + delay;
// If timer expiration is postponed, we have to do nothing but updating
// the timer expiration, because Expire() will reschedule itself to be
// executed at the correct time. If timer expiration is moved up, we
// have to reschedule Expire() (which would be executed too late otherwise)
if (end < m_end)
{
// timer expiration is moved up
m_timeoutEvent.Cancel ();
m_timeoutEvent = Simulator::Schedule (delay, &WifiTxTimer::Expire, this);
}
m_end = end;
}
}
void
WifiTxTimer::Expire (void)
{
NS_LOG_FUNCTION (this);
Time now = Simulator::Now ();
if (m_end == now)
{
m_impl->Invoke ();
}
else
{
m_timeoutEvent = Simulator::Schedule (m_end - now, &WifiTxTimer::Expire, this);
}
}
@@ -101,7 +128,7 @@ WifiTxTimer::Cancel (void)
{
NS_LOG_FUNCTION (this << GetReasonString (m_reason));
m_timeoutEvent.Cancel ();
m_endRxEvent = 0;
m_impl = 0;
}
Time

View File

@@ -41,7 +41,7 @@ typedef std::unordered_map <uint16_t /* staId */, Ptr<WifiPsdu> /* PSDU */> Wifi
* \ingroup wifi
*
* This class is used to handle the timer that a station starts when transmitting
* a frame that solicits a response. The timeout can be rescheduled (only once)
* a frame that solicits a response. The timeout can be rescheduled (multiple times)
* when the RXSTART.indication is received from the PHY.
*/
class WifiTxTimer
@@ -88,8 +88,7 @@ public:
/**
* Reschedule the timer to time out the given amount of time from the moment
* this function is called. Note that the timer must be running and must not
* have been already rescheduled.
* this function is called. Note that nothing is done if the timer is not running.
*
* \param delay the time to the expiration of the timer
*/
@@ -185,6 +184,11 @@ private:
template<typename MEM, typename OBJ, typename... Args>
void Timeout (MEM mem_ptr, OBJ obj, Args... args);
/**
* Internal callback invoked when the timer expires.
*/
void Expire (void);
/**
* This method is called when the timer expires to feed the MPDU response
* timeout callback.
@@ -216,8 +220,9 @@ private:
EventId m_timeoutEvent; //!< the timeout event after a missing response
Reason m_reason; //!< the reason why the timer was started
Ptr<EventImpl> m_endRxEvent; //!< event to schedule upon RXSTART.indication
bool m_rescheduled; //!< whether the timer has been already rescheduled
Ptr<EventImpl> m_impl; /**< the timer implementation, which contains the bound
callback function and arguments */
Time m_end; //!< the absolute time when the timer will expire
/// the MPDU response timeout callback
mutable MpduResponseTimeout m_mpduResponseTimeoutCallback;
@@ -242,13 +247,13 @@ WifiTxTimer::Set (Reason reason, const Time &delay, MEM mem_ptr, OBJ obj, Args..
{
typedef void (WifiTxTimer::*TimeoutType)(MEM, OBJ, Args...);
m_timeoutEvent = Simulator::Schedule<TimeoutType> (delay, &WifiTxTimer::Timeout, this, mem_ptr, obj, args...);
m_timeoutEvent = Simulator::Schedule (delay, &WifiTxTimer::Expire, this);
m_reason = reason;
m_rescheduled = false;
m_end = Simulator::Now () + delay;
// create an event to schedule if the PHY notifies the reception of a response
m_endRxEvent = Ptr<EventImpl> (MakeEvent<TimeoutType> (&WifiTxTimer::Timeout, this, mem_ptr, obj,
std::forward<Args> (args)... ), false);
// create an event to invoke when the timer expires
m_impl = Ptr<EventImpl> (MakeEvent<TimeoutType> (&WifiTxTimer::Timeout, this, mem_ptr, obj,
std::forward<Args> (args)... ), false);
}
template<typename MEM, typename OBJ, typename... Args>