wifi: Store stations expected to respond in WifiTxTimer

This commit is contained in:
Stefano Avallone
2023-05-31 11:53:39 +02:00
committed by Stefano Avallone
parent 6f8b3a039d
commit 1399177627
6 changed files with 112 additions and 79 deletions

View File

@@ -502,6 +502,7 @@ FrameExchangeManager::SendMpdu()
NS_ASSERT(!m_txTimer.IsRunning());
m_txTimer.Set(WifiTxTimer::WAIT_NORMAL_ACK,
timeout,
{m_mpdu->GetHeader().GetAddr1()},
&FrameExchangeManager::NormalAckTimeout,
this,
m_mpdu,
@@ -727,6 +728,7 @@ FrameExchangeManager::SendRts(const WifiTxParameters& txParams)
NS_ASSERT(!m_txTimer.IsRunning());
m_txTimer.Set(WifiTxTimer::WAIT_CTS,
timeout,
{receiver},
&FrameExchangeManager::CtsTimeout,
this,
mpdu,

View File

@@ -397,6 +397,7 @@ HeFrameExchangeManager::SendMuRts(const WifiTxParameters& txParams)
NS_ASSERT(!m_txTimer.IsRunning());
m_txTimer.Set(WifiTxTimer::WAIT_CTS_AFTER_MU_RTS,
timeout,
m_sentRtsTo,
&HeFrameExchangeManager::CtsAfterMuRtsTimeout,
this,
mpdu,
@@ -516,6 +517,7 @@ HeFrameExchangeManager::SendPsduMap()
Ptr<WifiMpdu> mpdu = nullptr;
Ptr<WifiPsdu> psdu = nullptr;
WifiTxVector txVector;
std::set<Mac48Address> staExpectResponseFrom;
// Compute the type of TX timer to set depending on the acknowledgment method
@@ -552,10 +554,11 @@ HeFrameExchangeManager::SendPsduMap()
timerType = WifiTxTimer::WAIT_NORMAL_ACK_AFTER_DL_MU_PPDU;
responseTxVector =
&acknowledgment->stationsReplyingWithNormalAck.begin()->second.ackTxVector;
psdu =
GetPsduTo(acknowledgment->stationsReplyingWithNormalAck.begin()->first, m_psduMap);
auto from = acknowledgment->stationsReplyingWithNormalAck.begin()->first;
psdu = GetPsduTo(from, m_psduMap);
NS_ASSERT(psdu->GetNMpdus() == 1);
mpdu = *psdu->begin();
staExpectResponseFrom.insert(from);
}
else if (!acknowledgment->stationsReplyingWithBlockAck.empty())
{
@@ -563,8 +566,9 @@ HeFrameExchangeManager::SendPsduMap()
timerType = WifiTxTimer::WAIT_BLOCK_ACK;
responseTxVector =
&acknowledgment->stationsReplyingWithBlockAck.begin()->second.blockAckTxVector;
psdu =
GetPsduTo(acknowledgment->stationsReplyingWithBlockAck.begin()->first, m_psduMap);
auto from = acknowledgment->stationsReplyingWithBlockAck.begin()->first;
psdu = GetPsduTo(from, m_psduMap);
staExpectResponseFrom.insert(from);
}
// else no station will reply immediately
}
@@ -608,10 +612,9 @@ HeFrameExchangeManager::SendPsduMap()
// we are transmitting the MU-BAR following the DL MU PPDU after a SIFS.
// m_psduMap and m_txParams are still the same as when the DL MU PPDU was sent.
// record the set of stations expected to send a BlockAck frame
m_staExpectTbPpduFrom.clear();
for (auto& station : acknowledgment->stationsReplyingWithBlockAck)
{
m_staExpectTbPpduFrom.insert(station.first);
staExpectResponseFrom.insert(station.first);
}
Ptr<WifiPsdu> triggerPsdu = GetWifiPsdu(m_triggerFrame, acknowledgment->muBarTxVector);
@@ -629,11 +632,11 @@ HeFrameExchangeManager::SendPsduMap()
m_txTimer.Set(WifiTxTimer::WAIT_BLOCK_ACKS_IN_TB_PPDU,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::BlockAcksInTbPpduTimeout,
this,
&m_psduMap,
&m_staExpectTbPpduFrom,
m_staExpectTbPpduFrom.size());
staExpectResponseFrom.size());
m_channelAccessManager->NotifyAckTimeoutStartNow(timeout);
ForwardPsduDown(triggerPsdu, acknowledgment->muBarTxVector);
@@ -654,15 +657,13 @@ HeFrameExchangeManager::SendPsduMap()
WifiDlMuAggregateTf* acknowledgment =
static_cast<WifiDlMuAggregateTf*>(m_txParams.m_acknowledgment.get());
// record the set of stations expected to send a BlockAck frame
m_staExpectTbPpduFrom.clear();
m_trigVector =
acknowledgment->stationsReplyingWithBlockAck.begin()->second.blockAckTxVector;
// record the set of stations expected to send a BlockAck frame
for (auto& station : acknowledgment->stationsReplyingWithBlockAck)
{
m_staExpectTbPpduFrom.insert(station.first);
staExpectResponseFrom.insert(station.first);
// check that the station that is expected to send a BlockAck frame is
// actually the receiver of a PSDU
auto psduMapIt = std::find_if(m_psduMap.begin(),
@@ -705,11 +706,9 @@ HeFrameExchangeManager::SendPsduMap()
static_cast<WifiUlMuMultiStaBa*>(m_txParams.m_acknowledgment.get());
// record the set of stations solicited by this Trigger Frame
m_staExpectTbPpduFrom.clear();
for (const auto& station : acknowledgment->stationsReceivingMultiStaBa)
{
m_staExpectTbPpduFrom.insert(station.first.first);
staExpectResponseFrom.insert(station.first.first);
}
// Reset stationsReceivingMultiStaBa, which will be filled as soon as
@@ -732,13 +731,11 @@ HeFrameExchangeManager::SendPsduMap()
NS_ASSERT(m_apMac);
// record the set of stations solicited by this Trigger Frame
m_staExpectTbPpduFrom.clear();
for (const auto& userInfo : trigger)
{
auto staIt = m_apMac->GetStaList(m_linkId).find(userInfo.GetAid12());
NS_ASSERT(staIt != m_apMac->GetStaList(m_linkId).end());
m_staExpectTbPpduFrom.insert(staIt->second);
staExpectResponseFrom.insert(staIt->second);
}
timerType = WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF;
@@ -755,10 +752,10 @@ HeFrameExchangeManager::SendPsduMap()
NS_ASSERT(m_psduMap.size() == 1);
timerType = WifiTxTimer::WAIT_BLOCK_ACK_AFTER_TB_PPDU;
NS_ASSERT(m_staMac && m_staMac->IsAssociated());
txVector = GetWifiRemoteStationManager()->GetBlockAckTxVector(
m_psduMap.begin()->second->GetAddr1(),
m_txParams.m_txVector);
auto recv = m_psduMap.begin()->second->GetAddr1();
txVector = GetWifiRemoteStationManager()->GetBlockAckTxVector(recv, m_txParams.m_txVector);
responseTxVector = &txVector;
staExpectResponseFrom.insert(recv);
}
/*
* QoS Null frames solicited by a BSRP Trigger Frame
@@ -828,6 +825,7 @@ HeFrameExchangeManager::SendPsduMap()
NS_ASSERT(mpdu);
m_txTimer.Set(timerType,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::NormalAckTimeout,
this,
mpdu,
@@ -837,6 +835,7 @@ HeFrameExchangeManager::SendPsduMap()
NS_ASSERT(psdu);
m_txTimer.Set(timerType,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::BlockAckTimeout,
this,
psdu,
@@ -845,25 +844,26 @@ HeFrameExchangeManager::SendPsduMap()
case WifiTxTimer::WAIT_BLOCK_ACKS_IN_TB_PPDU:
m_txTimer.Set(timerType,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::BlockAcksInTbPpduTimeout,
this,
&m_psduMap,
&m_staExpectTbPpduFrom,
m_staExpectTbPpduFrom.size());
staExpectResponseFrom.size());
break;
case WifiTxTimer::WAIT_TB_PPDU_AFTER_BASIC_TF:
case WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF:
m_txTimer.Set(timerType,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::TbPpduTimeout,
this,
&m_psduMap,
&m_staExpectTbPpduFrom,
m_staExpectTbPpduFrom.size());
staExpectResponseFrom.size());
break;
case WifiTxTimer::WAIT_BLOCK_ACK_AFTER_TB_PPDU:
m_txTimer.Set(timerType,
timeout,
staExpectResponseFrom,
&HeFrameExchangeManager::BlockAckAfterTbPpduTimeout,
this,
m_psduMap.begin()->second,
@@ -1256,20 +1256,19 @@ HeFrameExchangeManager::GetTxDuration(uint32_t ppduPayloadSize,
}
void
HeFrameExchangeManager::TbPpduTimeout(WifiPsduMap* psduMap,
const std::set<Mac48Address>* staMissedTbPpduFrom,
std::size_t nSolicitedStations)
HeFrameExchangeManager::TbPpduTimeout(WifiPsduMap* psduMap, std::size_t nSolicitedStations)
{
NS_LOG_FUNCTION(this << psduMap << staMissedTbPpduFrom->size() << nSolicitedStations);
const auto& staMissedTbPpduFrom = m_txTimer.GetStasExpectedToRespond();
NS_LOG_FUNCTION(this << psduMap << staMissedTbPpduFrom.size() << nSolicitedStations);
NS_ASSERT(psduMap);
NS_ASSERT(IsTrigger(*psduMap));
// This method is called if some station(s) did not send a TB PPDU
NS_ASSERT(!staMissedTbPpduFrom->empty());
NS_ASSERT(!staMissedTbPpduFrom.empty());
NS_ASSERT(m_edca);
if (staMissedTbPpduFrom->size() == nSolicitedStations)
if (staMissedTbPpduFrom.size() == nSolicitedStations)
{
// no station replied, the transmission failed
m_edca->UpdateFailedCw(m_linkId);
@@ -1286,10 +1285,8 @@ HeFrameExchangeManager::TbPpduTimeout(WifiPsduMap* psduMap,
}
void
HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
WifiPsduMap* psduMap,
const std::set<Mac48Address>* staMissedBlockAckFrom,
std::size_t nSolicitedStations)
HeFrameExchangeManager::BlockAcksInTbPpduTimeout(WifiPsduMap* psduMap,
std::size_t nSolicitedStations)
{
NS_LOG_FUNCTION(this << psduMap << nSolicitedStations);
@@ -1299,11 +1296,12 @@ HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
m_txParams.m_acknowledgment->method == WifiAcknowledgment::DL_MU_TF_MU_BAR));
// This method is called if some station(s) did not send a BlockAck frame in a TB PPDU
NS_ASSERT(!staMissedBlockAckFrom->empty());
const auto& staMissedBlockAckFrom = m_txTimer.GetStasExpectedToRespond();
NS_ASSERT(!staMissedBlockAckFrom.empty());
bool resetCw;
if (staMissedBlockAckFrom->size() == nSolicitedStations)
if (staMissedBlockAckFrom.size() == nSolicitedStations)
{
// no station replied, the transmission failed
// call ReportDataFailed to increase SRC/LRC
@@ -1322,7 +1320,7 @@ HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
m_triggerFrame = nullptr;
}
for (const auto& sta : *staMissedBlockAckFrom)
for (const auto& sta : staMissedBlockAckFrom)
{
Ptr<WifiPsdu> psdu = GetPsduTo(sta, *psduMap);
NS_ASSERT(psdu);
@@ -1346,7 +1344,7 @@ HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
m_edca->UpdateFailedCw(m_linkId);
}
if (staMissedBlockAckFrom->size() == nSolicitedStations)
if (staMissedBlockAckFrom.size() == nSolicitedStations)
{
// no station replied, the transmission failed
TransmissionFailed();
@@ -2191,7 +2189,7 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
static_cast<WifiUlMuMultiStaBa*>(m_txParams.m_acknowledgment.get());
std::size_t index = acknowledgment->baType.m_bitmapLen.size();
if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
if (m_txTimer.GetStasExpectedToRespond().count(sender) == 0)
{
NS_LOG_WARN("Received a TB PPDU from an unexpected station: " << sender);
return;
@@ -2252,9 +2250,9 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
}
// remove the sender from the set of stations that are expected to send a TB PPDU
m_staExpectTbPpduFrom.erase(sender);
m_txTimer.GotResponseFrom(sender);
if (m_staExpectTbPpduFrom.empty())
if (m_txTimer.GetStasExpectedToRespond().empty())
{
// we do not expect any other BlockAck frame
m_txTimer.Cancel();
@@ -2280,7 +2278,7 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
{
const auto& sender = hdr.GetAddr2();
if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
if (m_txTimer.GetStasExpectedToRespond().count(sender) == 0)
{
NS_LOG_WARN("Received a TB PPDU from an unexpected station: " << sender);
return;
@@ -2294,9 +2292,9 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
NS_LOG_DEBUG("Received a QoS Null frame in a TB PPDU from " << sender);
// remove the sender from the set of stations that are expected to send a TB PPDU
m_staExpectTbPpduFrom.erase(sender);
m_txTimer.GotResponseFrom(sender);
if (m_staExpectTbPpduFrom.empty())
if (m_txTimer.GetStasExpectedToRespond().empty())
{
// we do not expect any other response
m_txTimer.Cancel();
@@ -2411,13 +2409,15 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
m_txParams.m_txVector);
// remove the sender from the set of stations that are expected to send a BlockAck
if (m_staExpectTbPpduFrom.erase(sender) == 0)
if (m_txTimer.GetStasExpectedToRespond().count(sender) == 0)
{
NS_LOG_WARN("Received a BlockAck from an unexpected stations: " << sender);
return;
}
if (m_staExpectTbPpduFrom.empty())
m_txTimer.GotResponseFrom(sender);
if (m_txTimer.GetStasExpectedToRespond().empty())
{
// we do not expect any other BlockAck frame
m_txTimer.Cancel();
@@ -2663,7 +2663,7 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
static_cast<WifiUlMuMultiStaBa*>(m_txParams.m_acknowledgment.get());
std::size_t index = acknowledgment->baType.m_bitmapLen.size();
if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
if (m_txTimer.GetStasExpectedToRespond().count(sender) == 0)
{
NS_LOG_WARN("Received a TB PPDU from an unexpected station: " << sender);
return;
@@ -2709,9 +2709,9 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
}
// remove the sender from the set of stations that are expected to send a TB PPDU
m_staExpectTbPpduFrom.erase(sender);
m_txTimer.GotResponseFrom(sender);
if (m_staExpectTbPpduFrom.empty())
if (m_txTimer.GetStasExpectedToRespond().empty())
{
// we do not expect any other BlockAck frame
m_txTimer.Cancel();
@@ -2736,7 +2736,7 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
{
Mac48Address sender = psdu->GetAddr2();
if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
if (m_txTimer.GetStasExpectedToRespond().count(sender) == 0)
{
NS_LOG_WARN("Received a TB PPDU from an unexpected station: " << sender);
return;
@@ -2752,9 +2752,9 @@ HeFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
NS_LOG_DEBUG("Received QoS Null frames in a TB PPDU from " << sender);
// remove the sender from the set of stations that are expected to send a TB PPDU
m_staExpectTbPpduFrom.erase(sender);
m_txTimer.GotResponseFrom(sender);
if (m_staExpectTbPpduFrom.empty())
if (m_txTimer.GetStasExpectedToRespond().empty())
{
// we do not expect any other response
m_txTimer.Cancel();

View File

@@ -262,12 +262,9 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
* expected BlockAck frames were received.
*
* \param psduMap a pointer to PSDU map transmitted in a DL MU PPDU
* \param staMissedBlockAckFrom set of stations we missed a BlockAck frame from
* \param nSolicitedStations the number of stations solicited to send a TB PPDU
*/
virtual void BlockAcksInTbPpduTimeout(WifiPsduMap* psduMap,
const std::set<Mac48Address>* staMissedBlockAckFrom,
std::size_t nSolicitedStations);
virtual void BlockAcksInTbPpduTimeout(WifiPsduMap* psduMap, std::size_t nSolicitedStations);
/**
* Take the necessary actions after that some TB PPDUs are missing in
@@ -275,12 +272,9 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
* expected TB PPDUs were received.
*
* \param psduMap a pointer to PSDU map transmitted in a DL MU PPDU
* \param staMissedTbPpduFrom set of stations we missed a TB PPDU from
* \param nSolicitedStations the number of stations solicited to send a TB PPDU
*/
virtual void TbPpduTimeout(WifiPsduMap* psduMap,
const std::set<Mac48Address>* staMissedTbPpduFrom,
std::size_t nSolicitedStations);
virtual void TbPpduTimeout(WifiPsduMap* psduMap, std::size_t nSolicitedStations);
/**
* Take the necessary actions after that a Block Ack is missing after a
@@ -379,14 +373,13 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
Time durationId,
double snr);
WifiPsduMap m_psduMap; //!< the A-MPDU being transmitted
WifiTxParameters m_txParams; //!< the TX parameters for the current PPDU
Ptr<MultiUserScheduler> m_muScheduler; //!< Multi-user Scheduler (HE APs only)
Ptr<WifiMpdu> m_triggerFrame; //!< Trigger Frame being sent
std::set<Mac48Address> m_staExpectTbPpduFrom; //!< set of stations expected to send a TB PPDU
EventId m_multiStaBaEvent; //!< Sending a Multi-STA BlockAck event
MuSnrTag m_muSnrTag; //!< Tag to attach to Multi-STA BlockAck frames
bool m_triggerFrameInAmpdu; //!< True if the received A-MPDU contains an MU-BAR
WifiPsduMap m_psduMap; //!< the A-MPDU being transmitted
WifiTxParameters m_txParams; //!< the TX parameters for the current PPDU
Ptr<MultiUserScheduler> m_muScheduler; //!< Multi-user Scheduler (HE APs only)
Ptr<WifiMpdu> m_triggerFrame; //!< Trigger Frame being sent
EventId m_multiStaBaEvent; //!< Sending a Multi-STA BlockAck event
MuSnrTag m_muSnrTag; //!< Tag to attach to Multi-STA BlockAck frames
bool m_triggerFrameInAmpdu; //!< True if the received A-MPDU contains an MU-BAR
};
} // namespace ns3

View File

@@ -1016,6 +1016,7 @@ HtFrameExchangeManager::SendPsdu()
NS_ASSERT(!m_txTimer.IsRunning());
m_txTimer.Set(WifiTxTimer::WAIT_BLOCK_ACK,
timeout,
{m_psdu->GetAddr1()},
&HtFrameExchangeManager::BlockAckTimeout,
this,
m_psdu,

View File

@@ -129,6 +129,19 @@ WifiTxTimer::Cancel()
NS_LOG_FUNCTION(this << GetReasonString(m_reason));
m_timeoutEvent.Cancel();
m_impl = nullptr;
m_staExpectResponseFrom.clear();
}
void
WifiTxTimer::GotResponseFrom(const Mac48Address& from)
{
m_staExpectResponseFrom.erase(from);
}
const std::set<Mac48Address>&
WifiTxTimer::GetStasExpectedToRespond() const
{
return m_staExpectResponseFrom;
}
Time
@@ -174,13 +187,14 @@ WifiTxTimer::SetPsduMapResponseTimeoutCallback(PsduMapResponseTimeout callback)
}
void
WifiTxTimer::FeedTraceSource(WifiPsduMap* psduMap,
std::set<Mac48Address>* missingStations,
std::size_t nTotalStations)
WifiTxTimer::FeedTraceSource(WifiPsduMap* psduMap, std::size_t nTotalStations)
{
if (!m_psduMapResponseTimeoutCallback.IsNull())
{
m_psduMapResponseTimeoutCallback(m_reason, psduMap, missingStations, nTotalStations);
m_psduMapResponseTimeoutCallback(m_reason,
psduMap,
&m_staExpectResponseFrom,
nTotalStations);
}
}

View File

@@ -81,12 +81,18 @@ class WifiTxTimer
* \tparam Args \deduced Type template parameter pack
* \param reason the reason why the timer was started
* \param delay the time to the expiration of the timer
* \param from the set of stations we expect to receive a response from
* \param mem_ptr Member method pointer to invoke
* \param obj The object on which to invoke the member method
* \param args The arguments to pass to the invoked method
*/
template <typename MEM, typename OBJ, typename... Args>
void Set(Reason reason, const Time& delay, MEM mem_ptr, OBJ obj, Args... args);
void Set(Reason reason,
const Time& delay,
const std::set<Mac48Address>& from,
MEM mem_ptr,
OBJ obj,
Args... args);
/**
* Reschedule the timer to time out the given amount of time from the moment
@@ -124,6 +130,18 @@ class WifiTxTimer
*/
void Cancel();
/**
* Notify that a response was got from the given station.
*
* \param from the MAC address of the given station
*/
void GotResponseFrom(const Mac48Address& from);
/**
* \return the set of stations that are still expected to respond
*/
const std::set<Mac48Address>& GetStasExpectedToRespond() const;
/**
* Get the remaining time until the timer will expire.
*
@@ -216,18 +234,17 @@ class WifiTxTimer
* timeout callback.
*
* \param psduMap the PSDU map for which not all responses were received
* \param missingStations the set of stations that did not respond
* \param nTotalStations the total number of expected responses
*/
void FeedTraceSource(WifiPsduMap* psduMap,
std::set<Mac48Address>* missingStations,
std::size_t nTotalStations);
void FeedTraceSource(WifiPsduMap* psduMap, std::size_t nTotalStations);
EventId m_timeoutEvent; //!< the timeout event after a missing response
Reason m_reason; //!< the reason why the timer was started
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
std::set<Mac48Address>
m_staExpectResponseFrom; //!< the set of stations we expect to receive a response from
/// the MPDU response timeout callback
mutable MpduResponseTimeout m_mpduResponseTimeoutCallback;
@@ -248,13 +265,19 @@ namespace ns3
template <typename MEM, typename OBJ, typename... Args>
void
WifiTxTimer::Set(Reason reason, const Time& delay, MEM mem_ptr, OBJ obj, Args... args)
WifiTxTimer::Set(Reason reason,
const Time& delay,
const std::set<Mac48Address>& from,
MEM mem_ptr,
OBJ obj,
Args... args)
{
typedef void (WifiTxTimer::*TimeoutType)(MEM, OBJ, Args...);
m_timeoutEvent = Simulator::Schedule(delay, &WifiTxTimer::Expire, this);
m_reason = reason;
m_end = Simulator::Now() + delay;
m_staExpectResponseFrom = from;
// create an event to invoke when the timer expires
m_impl = Ptr<EventImpl>(MakeEvent<TimeoutType>(&WifiTxTimer::Timeout,