wifi: Generate backoff if needed when requesting channel access

This commit is contained in:
Stefano Avallone
2023-09-19 16:43:58 +02:00
committed by Stefano Avallone
parent 7c778e74d3
commit 3cea322710
6 changed files with 71 additions and 16 deletions

View File

@@ -165,7 +165,7 @@ cpp_examples = [
"True",
),
(
"wifi-eht-network --simulationTime=0.22 --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=4 --frequency2=6 --minExpectedThroughput=35 --maxExpectedThroughput=280",
"wifi-eht-network --simulationTime=0.23 --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=5 --frequency2=6 --minExpectedThroughput=35 --maxExpectedThroughput=280",
"True",
"True",
),

View File

@@ -391,9 +391,11 @@ ChannelAccessManager::IsBusy() const
}
bool
ChannelAccessManager::NeedBackoffUponAccess(Ptr<Txop> txop)
ChannelAccessManager::NeedBackoffUponAccess(Ptr<Txop> txop,
bool hadFramesToTransmit,
bool checkMediumBusy)
{
NS_LOG_FUNCTION(this << txop);
NS_LOG_FUNCTION(this << txop << hadFramesToTransmit << checkMediumBusy);
// No backoff needed if in sleep mode, off or when using another EMLSR link
if (m_sleeping || m_off || m_usingOtherEmlsrLink)
@@ -424,10 +426,10 @@ 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(m_linkId) && txop->GetAccessStatus(m_linkId) != Txop::GRANTED &&
txop->GetBackoffSlots(m_linkId) == 0)
if (!hadFramesToTransmit && txop->HasFramesToTransmit(m_linkId) &&
txop->GetAccessStatus(m_linkId) != Txop::GRANTED && txop->GetBackoffSlots(m_linkId) == 0)
{
if (!IsBusy())
if (checkMediumBusy && !IsBusy())
{
// medium idle. If this is a DCF, use immediate access (we can transmit
// in a DIFS if the medium remains idle). If this is an EDCAF, update

View File

@@ -109,13 +109,22 @@ class ChannelAccessManager : public Object
void Add(Ptr<Txop> txop);
/**
* Determine if a new backoff needs to be generated when a packet is queued
* for transmission.
* Determine if a new backoff needs to be generated as per letter a) of Section 10.23.2.2
* of IEEE 802.11-2020 ("EDCA backoff procedure"). This method is called upon the occurrence
* of events such as the enqueuing of a packet or the unblocking of some links after they
* have been blocked for some reason (e.g., wait for ADDBA Response, wait for TX on another
* EMLSR link to finish, etc.). The <i>checkMediumBusy</i> argument allows to generate a new
* backoff regardless of the busy/idle state of the medium, as per Section 35.3.16.4 of
* 802.11be D4.0.
*
* \param txop the Txop requesting to generate a backoff
* \param hadFramesToTransmit whether packets available for transmission were queued just
* before the occurrence of the event triggering this call
* \param checkMediumBusy whether generation of backoff (also) depends on the busy/idle state
* of the medium
* \return true if backoff needs to be generated, false otherwise
*/
bool NeedBackoffUponAccess(Ptr<Txop> txop);
bool NeedBackoffUponAccess(Ptr<Txop> txop, bool hadFramesToTransmit, bool checkMediumBusy);
/**
* \param txop a Txop

View File

@@ -535,12 +535,13 @@ Txop::Queue(Ptr<WifiMpdu> mpdu)
{
NS_LOG_FUNCTION(this << *mpdu);
const auto linkIds = m_mac->GetMacQueueScheduler()->GetLinkIds(m_queue->GetAc(), mpdu);
std::map<uint8_t, bool> hasFramesToTransmit;
// save the status of the AC queues before enqueuing the MPDU (required to determine if
// backoff is needed)
for (const auto linkId : linkIds)
{
if (m_mac->GetChannelAccessManager(linkId)->NeedBackoffUponAccess(this))
{
GenerateBackoff(linkId);
}
hasFramesToTransmit[linkId] = HasFramesToTransmit(linkId);
}
m_queue->Enqueue(mpdu);
for (const auto linkId : linkIds)
@@ -551,7 +552,11 @@ Txop::Queue(Ptr<WifiMpdu> mpdu)
// packet
if (auto& event = GetLink(linkId).accessRequest.event; !event.IsRunning())
{
event = Simulator::ScheduleNow(&Txop::StartAccessIfNeeded, this, linkId);
event = Simulator::ScheduleNow(&Txop::StartAccessAfterEvent,
this,
linkId,
hasFramesToTransmit.at(linkId),
true);
}
}
}
@@ -564,6 +569,27 @@ Txop::AssignStreams(int64_t stream)
return 1;
}
void
Txop::StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy)
{
NS_LOG_FUNCTION(this << +linkId << hadFramesToTransmit << checkMediumBusy);
if (GetLink(linkId).access != NOT_REQUESTED || !HasFramesToTransmit(linkId))
{
NS_LOG_DEBUG("No need to request channel access on link " << +linkId);
return;
}
if (m_mac->GetChannelAccessManager(linkId)->NeedBackoffUponAccess(this,
hadFramesToTransmit,
checkMediumBusy))
{
GenerateBackoff(linkId);
}
m_mac->GetChannelAccessManager(linkId)->RequestAccess(this);
}
void
Txop::StartAccessIfNeeded(uint8_t linkId)
{

View File

@@ -395,6 +395,23 @@ class Txop : public Object
*/
virtual ChannelAccessStatus GetAccessStatus(uint8_t linkId) const;
/**
* Request channel access on the given link after the occurrence of an event that possibly
* requires to generate a new backoff value. Examples of such an event are: a packet has been
* enqueued by the upper layer; the given link has been unblocked after being blocked for some
* reason (e.g., wait for ADDBA Response, wait for TX on another EMLSR link to finish, etc.);
* the PHY operating on the given link just woke up from sleep mode. The <i>checkMediumBusy</i>
* argument is forwarded to the NeedBackoffUponAccess method of the ChannelAccessManager.
*
* \param linkId the ID of the given link
* \param hadFramesToTransmit whether packets available for transmission were queued just
* before the occurrence of the event causing this channel access
* request
* \param checkMediumBusy whether generation of backoff (also) depends on the busy/idle state
* of the medium
*/
void StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy);
/**
* Request access from Txop on the given link if needed.
*

View File

@@ -806,11 +806,12 @@ ChannelAccessManagerTest<TxopType>::DoAccessRequest(uint64_t txTime,
uint64_t expectedGrantTime,
Ptr<TxopTest<TxopType>> state)
{
if (m_ChannelAccessManager->NeedBackoffUponAccess(state))
auto hadFramesToTransmit = state->HasFramesToTransmit(SINGLE_LINK_OP_ID);
state->QueueTx(txTime, expectedGrantTime);
if (m_ChannelAccessManager->NeedBackoffUponAccess(state, hadFramesToTransmit, true))
{
state->GenerateBackoff(0);
}
state->QueueTx(txTime, expectedGrantTime);
m_ChannelAccessManager->RequestAccess(state);
}