wifi: Fix EDCA immediate channel access

...when channel access is requested at a slot boundary.
This commit is contained in:
Stefano Avallone
2025-08-20 16:25:02 +02:00
parent d8feca9156
commit 7cd1a70131
25 changed files with 29 additions and 33 deletions

View File

@@ -45,6 +45,7 @@ The wimax module was removed and moved to the ns-3 App Store.
- (internet) #1251 - Added check for longest prefix match in GlobalRouting
- (wifi) Block transmission on other EMLSR links as soon as it is detected that the main PHY is receiving an A-MPDU, to prevent that the EMLSR client starts an UL TXOP before the end of the A-MPDU
- (wifi) EMLSR clients can switch to listening operations when receiving the MAC header of a broadcast frame that is not a Trigger Frame nor a Multi-STA BA
- (wifi) Immediate channel access should not be postponed by a backoff slot if channel access is requested at a slot boundary
## Release 3.45

View File

@@ -195,7 +195,7 @@ cpp_examples = [
"True",
),
(
"wifi-eht-network --simulationTime=0.25s --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=8 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=550 --RngRun=3",
"wifi-eht-network --simulationTime=0.25s --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=8 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=550",
"True",
"True",
),

View File

@@ -17,6 +17,7 @@
#include "ns3/log.h"
#include "ns3/simulator.h"
#include <cmath>
#include <sstream>
#undef NS_LOG_APPEND_CONTEXT
@@ -591,13 +592,13 @@ ChannelAccessManager::RequestAccess(Ptr<Txop> txop)
*/
Time accessGrantStart = GetAccessGrantStart() + (txop->GetAifsn(m_linkId) * GetSlot());
if (txop->IsQosTxop() && txop->GetBackoffStart(m_linkId) > accessGrantStart)
if (const auto diff = txop->GetBackoffStart(m_linkId) - accessGrantStart;
txop->IsQosTxop() && diff.IsStrictlyPositive())
{
// The backoff start time reported by the EDCAF is more recent than the last
// time the medium was busy plus an AIFS, hence we need to align it to the
// next slot boundary.
Time diff = txop->GetBackoffStart(m_linkId) - accessGrantStart;
uint32_t nIntSlots = (diff / GetSlot()).GetHigh() + 1;
// The backoff start time reported by the EDCAF is more recent than the last time the medium
// was busy plus an AIFS, hence we need to align it to the next slot boundary.
const auto div = diff / GetSlot();
const uint32_t nIntSlots = div.GetHigh() + (div.GetLow() > 0 ? 1 : 0);
txop->UpdateBackoffSlotsNow(0, accessGrantStart + (nIntSlots * GetSlot()), m_linkId);
}

View File

@@ -1750,9 +1750,9 @@ LargestIdlePrimaryChannelTest::DoRun()
* Backoff Backoff Backoff value #3, backoff
* value #0 value #1 value #2 unblock queue value
* | ┌─────┐ | | | ┌─────┐ ┌────┐ |
* | ┌───┐ │Assoc│ | |Decrement| |Decrement| |Decrement│ADDBA│ │QoS │ |
* | │ACK│ │Resp │ |AIFS| backoff |slot| backoff |slot| backoff │ Req │. .│data│ |
* ──┬─────┬┴───┴──┴─────┴┬───┬────────────────────────────────────────────┴─────┴───┴────┴┬───┬──
* | ┌───┐ │Assoc│ | | Decrement | Decrement | Decrement │ADDBA│ │QoS │ |
* | │ACK│ │Resp │ |AIFS| backoff | backoff | backoff │ Req │. .│data│ |
* ──┬─────┬┴───┴──┴─────┴┬───┬────────────────────────────────────────┴─────┴───┴────┴┬───┬──
* │Assoc│ │ACK│ │ACK│
* │ Req │ └───┘ └───┘
* └─────┘
@@ -2164,10 +2164,6 @@ BackoffGenerationTest::BackoffGenerated(AcIndex ac, uint32_t backoff, uint8_t li
offset,
"Backoff value generated too early");
m_nextBackoffGen.Cancel();
// we get here when the backoff expired but no transmission occurred, thus we have
// generated a new backoff value and we will start decrementing the counter in a slot
delay = m_apMac->GetWifiPhy(linkId)->GetSlot();
}
if (m_nGenBackoff < nValues)

View File

@@ -155,7 +155,7 @@ WifiUseAvailBwTest::Transmit(uint8_t bss,
client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
client->SetRemote(m_sockets[0]);
m_apDevices.Get(0)->GetNode()->AddApplication(client);
client->SetStartTime(Seconds(0)); // start now
client->SetStartTime(TimeStep(1)); // start shortly after the start of PPDU in BSS 1
client->SetStopTime(Seconds(1)); // stop in a second
client->Initialize();
@@ -470,20 +470,18 @@ WifiDynamicBwOpTestSuite::WifiDynamicBwOpTestSuite()
AddTestCase(
new WifiUseAvailBwTest({"{50, 160, BAND_5GHZ, 5}", "{42, 80, BAND_5GHZ, 2}"}, MHz_u{80}),
TestCase::Duration::QUICK);
// clang-format off
/**
* ───────────────────────────── primary 160 ─────────────────────────────
* ────────────── primary 160 ──────────────
* primary20
* ┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┐
* ┌────┬────┬────┬────┬────┬────┬────┬────┬────────┬────┬────┬────────┬────────┐
* BSS 0 │ 1 │ 5 │ 9 │ 13 │ 17 │ 21 │ 25 │ 29 │ 33 │ 37 │ 41 │ 45 │ 49 │ 53 │ 57 │ 61 │
* └────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────└────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────┘
* └────┴────┴────┴────┴────┴────┴────┴────┴────────┴────┴────┴────────┴────────┘
*
* ┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┐
* ┌────┬────┬────┬────┬────┬────┬────┬────┐
* BSS 1 │ 1 │ 5 │ 9 │ 13 │ 17 │ 21 │ 25 │ 29 │
* └────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────┘
* └────┴────┴────┴────┴────┴────┴────┴────┘
* primary20
*/
// clang-format on
AddTestCase(
new WifiUseAvailBwTest({"{31, 320, BAND_6GHZ, 10}", "{15, 160, BAND_6GHZ, 7}"}, 160),
TestCase::Duration::QUICK);