diff --git a/src/wifi/model/channel-access-manager.cc b/src/wifi/model/channel-access-manager.cc index 9996a94af..4af3e6a3b 100644 --- a/src/wifi/model/channel-access-manager.cc +++ b/src/wifi/model/channel-access-manager.cc @@ -264,7 +264,8 @@ ChannelAccessManager::NeedBackoffUponAccess (Ptr txop) * with that AC has now become non-empty and any other transmit queues * associated with that AC are empty; the medium is busy on the primary channel */ - if (!txop->HasFramesToTransmit () && !txop->GetLow ()->IsCfPeriod () && txop->GetBackoffSlots () == 0) + if (!txop->HasFramesToTransmit () && txop->GetAccessStatus () != Txop::GRANTED + && !txop->GetLow ()->IsCfPeriod () && txop->GetBackoffSlots () == 0) { if (!IsBusy ()) { @@ -322,7 +323,7 @@ ChannelAccessManager::RequestAccess (Ptr txop, bool isCfPeriod) } UpdateBackoff (); - NS_ASSERT (!txop->IsAccessRequested ()); + NS_ASSERT (txop->GetAccessStatus () != Txop::REQUESTED); txop->NotifyAccessRequested (); DoGrantDcfAccess (); DoRestartAccessTimeoutIfNeeded (); @@ -342,7 +343,7 @@ ChannelAccessManager::DoGrantDcfAccess (void) for (Txops::iterator i = m_txops.begin (); i != m_txops.end (); k++) { Ptr txop = *i; - if (txop->IsAccessRequested () + if (txop->GetAccessStatus () == Txop::REQUESTED && GetBackoffEndFor (txop) <= Simulator::Now () ) { /** @@ -356,7 +357,7 @@ ChannelAccessManager::DoGrantDcfAccess (void) for (Txops::iterator j = i; j != m_txops.end (); j++, k++) { Ptr otherTxop = *j; - if (otherTxop->IsAccessRequested () + if (otherTxop->GetAccessStatus () == Txop::REQUESTED && GetBackoffEndFor (otherTxop) <= Simulator::Now ()) { NS_LOG_DEBUG ("dcf " << k << " needs access. backoff expired. internal collision. slots=" << @@ -511,7 +512,7 @@ ChannelAccessManager::DoRestartAccessTimeoutIfNeeded (void) Time expectedBackoffEnd = Simulator::GetMaximumSimulationTime (); for (auto txop : m_txops) { - if (txop->IsAccessRequested ()) + if (txop->GetAccessStatus () == Txop::REQUESTED) { Time tmp = GetBackoffEndFor (txop); if (tmp > Simulator::Now ()) @@ -653,7 +654,7 @@ ChannelAccessManager::NotifySwitchingStartNow (Time duration) NS_ASSERT (txop->GetBackoffSlots () == 0); } txop->ResetCw (); - txop->m_accessRequested = false; + txop->m_access = Txop::NOT_REQUESTED; txop->NotifyChannelSwitching (); } @@ -712,7 +713,7 @@ ChannelAccessManager::NotifyWakeupNow (void) NS_ASSERT (txop->GetBackoffSlots () == 0); } txop->ResetCw (); - txop->m_accessRequested = false; + txop->m_access = Txop::NOT_REQUESTED; txop->NotifyWakeUp (); } } @@ -731,7 +732,7 @@ ChannelAccessManager::NotifyOnNow (void) NS_ASSERT (txop->GetBackoffSlots () == 0); } txop->ResetCw (); - txop->m_accessRequested = false; + txop->m_access = Txop::NOT_REQUESTED; txop->NotifyOn (); } } diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 4ebd13da1..e44e1af39 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -502,8 +502,10 @@ void QosTxop::NotifyAccessGranted (void) { NS_LOG_FUNCTION (this); - NS_ASSERT (m_accessRequested); - m_accessRequested = false; + // TODO FEM may have changed m_access to GRANTED, so the assert below holds not + // always true. Anyway, this function will soon be removed altogether. + // NS_ASSERT (m_access == REQUESTED); + m_access = NOT_REQUESTED; m_isAccessRequestedForRts = false; m_startTxop = Simulator::Now (); // discard the current packet if it is a QoS Data frame with expired lifetime @@ -994,7 +996,7 @@ QosTxop::RestartAccessIfNeeded (void) bool queueIsNotEmpty = !m_queue->IsEmpty (); if ((m_currentPacket != 0 || baManagerHasPackets || queueIsNotEmpty) - && !IsAccessRequested ()) + && m_access == NOT_REQUESTED) { Ptr item; if (m_currentPacket != 0) @@ -1031,7 +1033,7 @@ QosTxop::StartAccessIfNeeded (void) if (m_currentPacket == 0 && (baManagerHasPackets || queueIsNotEmpty) - && !IsAccessRequested ()) + && m_access == NOT_REQUESTED) { Ptr item = PeekNextFrame (); if (item != 0) diff --git a/src/wifi/model/txop.cc b/src/wifi/model/txop.cc index 85ded1293..dc9b16a47 100644 --- a/src/wifi/model/txop.cc +++ b/src/wifi/model/txop.cc @@ -89,7 +89,7 @@ Txop::Txop () m_cwMax (0), m_cw (0), m_backoff (0), - m_accessRequested (false), + m_access (NOT_REQUESTED), m_backoffSlots (0), m_backoffStart (Seconds (0.0)), m_currentPacket (0) @@ -342,7 +342,7 @@ Txop::RestartAccessIfNeeded (void) NS_LOG_FUNCTION (this); if ((m_currentPacket != 0 || !m_queue->IsEmpty ()) - && !IsAccessRequested () + && m_access == NOT_REQUESTED && !m_low->IsCfPeriod ()) { m_channelAccessManager->RequestAccess (this); @@ -355,7 +355,7 @@ Txop::StartAccessIfNeeded (void) NS_LOG_FUNCTION (this); if (m_currentPacket == 0 && !m_queue->IsEmpty () - && !IsAccessRequested () + && m_access == NOT_REQUESTED && !m_low->IsCfPeriod ()) { m_channelAccessManager->RequestAccess (this); @@ -457,25 +457,53 @@ Txop::GetFragmentPacket (WifiMacHeader *hdr) return fragment; } -bool -Txop::IsAccessRequested (void) const +Txop::ChannelAccessStatus +Txop::GetAccessStatus (void) const { - return m_accessRequested; + return m_access; } void Txop::NotifyAccessRequested (void) { NS_LOG_FUNCTION (this); - m_accessRequested = true; + m_access = REQUESTED; +} + +void +Txop::NotifyChannelAccessed (void) +{ + NS_LOG_FUNCTION (this); + m_access = GRANTED; +} + +void +Txop::NotifyChannelReleased (void) +{ + NS_LOG_FUNCTION (this); + m_access = NOT_REQUESTED; + GenerateBackoff (); + if (HasFramesToTransmit ()) + { + Simulator::ScheduleNow (&Txop::RequestAccess, this); + } +} + +void +Txop::RequestAccess (void) +{ + if (m_access == NOT_REQUESTED) + { + m_channelAccessManager->RequestAccess (this); + } } void Txop::NotifyAccessGranted (void) { NS_LOG_FUNCTION (this); - NS_ASSERT (m_accessRequested); - m_accessRequested = false; +// NS_ASSERT (m_access == REQUESTED); FEM may have changed m_access to GRANTED + m_access = NOT_REQUESTED; if (m_currentPacket == 0) { if (m_queue->IsEmpty ()) diff --git a/src/wifi/model/txop.h b/src/wifi/model/txop.h index 349b3c2e9..14595f3fc 100644 --- a/src/wifi/model/txop.h +++ b/src/wifi/model/txop.h @@ -94,6 +94,16 @@ public: */ typedef Callback > TxDropped; + /** + * Enumeration for channel access status + */ + enum ChannelAccessStatus + { + NOT_REQUESTED = 0, + REQUESTED, + GRANTED + }; + /** * Check for QoS TXOP. * @@ -329,6 +339,17 @@ public: */ virtual void TerminateTxop (void); + /** + * Called by the FrameExchangeManager to notify that channel access has + * been granted. + */ + virtual void NotifyChannelAccessed (void); + /** + * Called by the FrameExchangeManager to notify the completion of the transmissions. + * This method generates a new backoff and restarts access if needed. + */ + virtual void NotifyChannelReleased (void); + /** * Check if the next PCF transmission can fit in the remaining CFP duration. * @@ -350,10 +371,9 @@ public: int64_t AssignStreams (int64_t stream); /** - * \returns true if access has been requested for this function and - * has not been granted already, false otherwise. + * \return the current channel access status. */ - virtual bool IsAccessRequested (void) const; + virtual ChannelAccessStatus GetAccessStatus (void) const; /** * \param nSlots the number of slots of the backoff. @@ -401,6 +421,10 @@ protected: * Request access from Txop if needed. */ virtual void StartAccessIfNeeded (void); + /** + * Request access to the ChannelAccessManager + */ + void RequestAccess (void); /** * \returns the current value of the CW variable. The initial value is @@ -512,12 +536,12 @@ protected: Ptr m_stationManager; //!< the wifi remote station manager Ptr m_rng; //!< the random stream - uint32_t m_cwMin; //!< the minimum contention window - uint32_t m_cwMax; //!< the maximum contention window - uint32_t m_cw; //!< the current contention window - uint32_t m_backoff; //!< the current backoff - bool m_accessRequested; //!< flag whether channel access is already requested - uint32_t m_backoffSlots; //!< the number of backoff slots + uint32_t m_cwMin; //!< the minimum contention window + uint32_t m_cwMax; //!< the maximum contention window + uint32_t m_cw; //!< the current contention window + uint32_t m_backoff; //!< the current backoff + ChannelAccessStatus m_access; //!< channel access status + uint32_t m_backoffSlots; //!< the number of backoff slots /** * the backoffStart variable is used to keep track of the * time at which a backoff was started or the time at which