wifi: Generate backoff if needed when requesting channel access
This commit is contained in:
committed by
Stefano Avallone
parent
7c778e74d3
commit
3cea322710
@@ -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",
|
||||
),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user