From 13991776270611597f7ae7f5ffaf40a54fcc8d31 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 31 May 2023 11:53:39 +0200 Subject: [PATCH] wifi: Store stations expected to respond in WifiTxTimer --- src/wifi/model/frame-exchange-manager.cc | 2 + .../model/he/he-frame-exchange-manager.cc | 106 +++++++++--------- src/wifi/model/he/he-frame-exchange-manager.h | 25 ++--- .../model/ht/ht-frame-exchange-manager.cc | 1 + src/wifi/model/wifi-tx-timer.cc | 22 +++- src/wifi/model/wifi-tx-timer.h | 35 +++++- 6 files changed, 112 insertions(+), 79 deletions(-) diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index cbbdd555d..e59151e81 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -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, diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index 2ac69d5d7..d4b4c7bbd 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -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 mpdu = nullptr; Ptr psdu = nullptr; WifiTxVector txVector; + std::set 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 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(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(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* 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* 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 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 mpdu, static_cast(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 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 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 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 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 psdu, static_cast(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 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 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 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(); diff --git a/src/wifi/model/he/he-frame-exchange-manager.h b/src/wifi/model/he/he-frame-exchange-manager.h index 33f43a226..60fa7616c 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.h +++ b/src/wifi/model/he/he-frame-exchange-manager.h @@ -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* 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* 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 m_muScheduler; //!< Multi-user Scheduler (HE APs only) - Ptr m_triggerFrame; //!< Trigger Frame being sent - std::set 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 m_muScheduler; //!< Multi-user Scheduler (HE APs only) + Ptr 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 diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index 0c5b38e5a..ad2f63b13 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -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, diff --git a/src/wifi/model/wifi-tx-timer.cc b/src/wifi/model/wifi-tx-timer.cc index 24db46ffd..7ee49e25a 100644 --- a/src/wifi/model/wifi-tx-timer.cc +++ b/src/wifi/model/wifi-tx-timer.cc @@ -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& +WifiTxTimer::GetStasExpectedToRespond() const +{ + return m_staExpectResponseFrom; } Time @@ -174,13 +187,14 @@ WifiTxTimer::SetPsduMapResponseTimeoutCallback(PsduMapResponseTimeout callback) } void -WifiTxTimer::FeedTraceSource(WifiPsduMap* psduMap, - std::set* 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); } } diff --git a/src/wifi/model/wifi-tx-timer.h b/src/wifi/model/wifi-tx-timer.h index a1a03f54a..8df06c5b8 100644 --- a/src/wifi/model/wifi-tx-timer.h +++ b/src/wifi/model/wifi-tx-timer.h @@ -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 - void Set(Reason reason, const Time& delay, MEM mem_ptr, OBJ obj, Args... args); + void Set(Reason reason, + const Time& delay, + const std::set& 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& 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* 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 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 + 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 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& 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(MakeEvent(&WifiTxTimer::Timeout,