wifi: Txop holds a channel access state

This is needed because (Qos)Txop will no longer hold a current MPDU
that can be used to determine whether a frame exchange is ongoing.
This commit is contained in:
Stefano Avallone
2020-11-19 16:28:39 +01:00
parent 172f0f8598
commit 29cb1bfe0f
4 changed files with 85 additions and 30 deletions

View File

@@ -264,7 +264,8 @@ ChannelAccessManager::NeedBackoffUponAccess (Ptr<Txop> 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> 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> 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<Txop> 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 ();
}
}

View File

@@ -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<const WifiMacQueueItem> item;
if (m_currentPacket != 0)
@@ -1031,7 +1033,7 @@ QosTxop::StartAccessIfNeeded (void)
if (m_currentPacket == 0
&& (baManagerHasPackets || queueIsNotEmpty)
&& !IsAccessRequested ())
&& m_access == NOT_REQUESTED)
{
Ptr<const WifiMacQueueItem> item = PeekNextFrame ();
if (item != 0)

View File

@@ -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 ())

View File

@@ -94,6 +94,16 @@ public:
*/
typedef Callback <void, Ptr<const Packet> > 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<WifiRemoteStationManager> m_stationManager; //!< the wifi remote station manager
Ptr<UniformRandomVariable> 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