diff --git a/src/test/ns3wifi/wifi-mlo-udp-test-suite.cc b/src/test/ns3wifi/wifi-mlo-udp-test-suite.cc index e621b1d0f..4ed40eb78 100644 --- a/src/test/ns3wifi/wifi-mlo-udp-test-suite.cc +++ b/src/test/ns3wifi/wifi-mlo-udp-test-suite.cc @@ -295,6 +295,8 @@ WifiMloUdpTest::DoSetup() m_sink = nullptr; // other cases are not supported } + m_startAid = m_apMac->GetNextAssociationId(); + // schedule association/ML setup for one station at a time m_apMac->TraceConnectWithoutContext("AssociatedSta", MakeCallback(&WifiMloUdpTest::SetSsid, this)); diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 96b6b7427..e451f2709 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -209,7 +209,8 @@ ApWifiMac::GetTimeAccessParamsChecker() } ApWifiMac::ApWifiMac() - : m_enableBeaconGeneration(false) + : m_enableBeaconGeneration(false), + m_grpAddrBuIndicExp(0) { NS_LOG_FUNCTION(this); m_beaconTxop = CreateObjectWithAttributes("AcIndex", StringValue("AC_BEACON")); @@ -342,6 +343,14 @@ ApWifiMac::DoCompleteConfig() { GetLink(linkId).channelAccessManager->Add(m_beaconTxop); } + + // the value 'exp' for the Group Addressed BU Indication Exponent must be such that 2^(exp+1)-1 + // is at least equal to N-1, where N is the number of links (Sec. 35.3.15.1 of 802.11be D7.0). + // The max value for Group Addressed BU Indication Exponent is 3 (encoded in a 2-bit subfield) + while ((m_grpAddrBuIndicExp < 3) && ((1 << (m_grpAddrBuIndicExp + 1)) - 1 < GetNLinks() - 1)) + { + ++m_grpAddrBuIndicExp; + } } Ptr @@ -1153,6 +1162,7 @@ ApWifiMac::GetEhtOperation(uint8_t linkId) const } operation.SetMaxRxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX); operation.SetMaxTxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX); + operation.m_params.grpBuExp = m_grpAddrBuIndicExp; return operation; } @@ -2672,8 +2682,12 @@ ApWifiMac::GetNextAssociationId() const { const auto& links = GetLinks(); + // if this is an AP MLD, AIDs from 1 to N, where N is 2^(Group_addr_BU_Indic_Exp + 1) - 1 + // shall not be allocated (see Section 35.3.15.1 of 802.11be D7.0) + const uint16_t startAid = links.size() == 1 ? 1 : (1 << (m_grpAddrBuIndicExp + 1)); + // Return the first AID value between 1 and 2007 that is free for all the links - for (uint16_t nextAid = 1; nextAid <= 2007; ++nextAid) + for (uint16_t nextAid = startAid; nextAid <= 2007; ++nextAid) { if (std::none_of(links.cbegin(), links.cend(), [&](auto&& idLinkPair) { return GetStaList(idLinkPair.first).contains(nextAid); diff --git a/src/wifi/model/ap-wifi-mac.h b/src/wifi/model/ap-wifi-mac.h index 59e484c8f..a29c2cbf2 100644 --- a/src/wifi/model/ap-wifi-mac.h +++ b/src/wifi/model/ap-wifi-mac.h @@ -123,6 +123,9 @@ class ApWifiMac : public WifiMac */ uint16_t GetAssociationId(Mac48Address addr, uint8_t linkId) const; + /// @return the next Association ID to be allocated by the AP + uint16_t GetNextAssociationId() const; + /** * Get the ID of a link (if any) that has been setup with the station having the given MAC * address. The address can be either a link address or an MLD address. In the former case, @@ -623,11 +626,6 @@ class ApWifiMac : public WifiMac void DoDispose() override; void DoInitialize() override; - /** - * @return the next Association ID to be allocated by the AP - */ - uint16_t GetNextAssociationId() const; - Ptr m_beaconTxop; //!< Dedicated Txop for beacons bool m_enableBeaconGeneration; //!< Flag whether beacons are being generated Time m_beaconInterval; //!< Beacon interval @@ -639,6 +637,7 @@ class ApWifiMac : public WifiMac Time m_bsrLifetime; //!< Lifetime of Buffer Status Reports /// transition timeout events running for EMLSR clients std::map m_transitionTimeoutEvents; + uint8_t m_grpAddrBuIndicExp; //!< Group Addressed BU Indication Exponent of EHT Operation IE Ptr m_apEmlsrManager; ///< AP EMLSR Manager Ptr m_gcrManager; //!< GCR Manager diff --git a/src/wifi/test/wifi-emlsr-test.cc b/src/wifi/test/wifi-emlsr-test.cc index d3eccced2..9bf53f64c 100644 --- a/src/wifi/test/wifi-emlsr-test.cc +++ b/src/wifi/test/wifi-emlsr-test.cc @@ -485,6 +485,8 @@ EmlsrOperationsTestBase::DoSetup() m_ulSockets.back().SetProtocol(1); } + m_startAid = m_apMac->GetNextAssociationId(); + // schedule ML setup for one station at a time m_apMac->TraceConnectWithoutContext( "AssociatedSta", @@ -538,15 +540,15 @@ EmlsrOperationsTestBase::StaAssociated(uint16_t aid, Mac48Address /* addr */) // trigger establishment of BA agreement with AP as originator Simulator::Schedule(delay, [=, this]() { m_apMac->GetDevice()->GetNode()->AddApplication( - GetApplication(DOWNLINK, aid - 1, 4, 1000, m_establishBaDl.front())); + GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, m_establishBaDl.front())); }); } else if (!m_establishBaUl.empty()) { // trigger establishment of BA agreement with AP as recipient Simulator::Schedule(delay, [=, this]() { - m_staMacs[aid - 1]->GetDevice()->GetNode()->AddApplication( - GetApplication(UPLINK, aid - 1, 4, 1000, m_establishBaUl.front())); + m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication( + GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front())); }); } else @@ -573,20 +575,20 @@ EmlsrOperationsTestBase::BaEstablishedDl(Mac48Address recipient, // trigger establishment of BA agreement with AP as originator Simulator::Schedule(delay, [=, this]() { m_apMac->GetDevice()->GetNode()->AddApplication( - GetApplication(DOWNLINK, aid - 1, 4, 1000, *std::next(it))); + GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, *std::next(it))); }); } else if (!m_establishBaUl.empty()) { // trigger establishment of BA agreement with AP as recipient Simulator::Schedule(delay, [=, this]() { - m_staMacs[aid - 1]->GetDevice()->GetNode()->AddApplication( - GetApplication(UPLINK, aid - 1, 4, 1000, m_establishBaUl.front())); + m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication( + GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front())); }); } else { - Simulator::Schedule(delay, [=, this]() { SetSsid(aid - 1 + 1); }); + Simulator::Schedule(delay, [=, this]() { SetSsid(aid - m_startAid + 1); }); } } diff --git a/src/wifi/test/wifi-emlsr-test.h b/src/wifi/test/wifi-emlsr-test.h index d82680abd..32326367f 100644 --- a/src/wifi/test/wifi-emlsr-test.h +++ b/src/wifi/test/wifi-emlsr-test.h @@ -232,6 +232,7 @@ class EmlsrOperationsTestBase : public TestCase std::vector> m_staMacs; ///< MACs of the non-AP MLDs std::vector m_dlSockets; ///< packet socket address for DL traffic std::vector m_ulSockets; ///< packet socket address for UL traffic + uint16_t m_startAid{1}; ///< first AID to allocate to stations uint16_t m_lastAid{0}; ///< AID of last associated station Time m_duration{0}; ///< simulation duration std::map> diff --git a/src/wifi/test/wifi-mlo-test.cc b/src/wifi/test/wifi-mlo-test.cc index 362ce1bcf..1665f4975 100644 --- a/src/wifi/test/wifi-mlo-test.cc +++ b/src/wifi/test/wifi-mlo-test.cc @@ -270,7 +270,7 @@ AidAssignmentTest::AidAssignmentTest(const std::vector>& linkI m_linkChannels({"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}"}), m_linkIds(linkIds), m_assocType(assocType), - m_expectedAid(1) // AID for first station + m_expectedAid(1) // AID for first station (to be updated in case of AP MLD) { } @@ -363,12 +363,16 @@ AidAssignmentTest::DoSetup() "Assoc", MakeCallback(&AidAssignmentTest::SetSsid, this).Bind(DynamicCast(mac))); } + + auto apMac = StaticCast(StaticCast(apDevice.Get(0))->GetMac()); + m_expectedAid = m_startAid = apMac->GetNextAssociationId(); } void AidAssignmentTest::SetSsid(Ptr staMac, Mac48Address /* apAddr */) { const auto aid = staMac->GetAssociationId(); + std::size_t index = aid - m_startAid; std::stringstream linksStr; const auto setupLinks = staMac->GetSetupLinkIds(); @@ -382,19 +386,17 @@ AidAssignmentTest::SetSsid(Ptr staMac, Mac48Address /* apAddr */) // if ML setup is performed, check that the requested links have been setup; otherwise, link 0 // only is setup const auto expectedLinks = - (m_assocType == WifiAssocType::ML_SETUP ? m_linkIds.at(aid - 1) + (m_assocType == WifiAssocType::ML_SETUP ? m_linkIds.at(index) : std::set{SINGLE_LINK_OP_ID}); NS_TEST_EXPECT_MSG_EQ((staMac->GetSetupLinkIds() == expectedLinks), true, "Unexpected set of setup links " << linksStr.str()); - if (m_expectedAid < m_staDevices.GetN()) + if (++index < m_staDevices.GetN()) { // let the next STA associate with the AP - StaticCast(m_staDevices.Get(m_expectedAid)) - ->GetMac() - ->SetSsid(Ssid("ns-3-ssid")); + StaticCast(m_staDevices.Get(index))->GetMac()->SetSsid(Ssid("ns-3-ssid")); ++m_expectedAid; } else @@ -409,7 +411,9 @@ AidAssignmentTest::DoRun() Simulator::Stop(Seconds(5)); // simulation will stop earlier if all STAs complete association Simulator::Run(); - NS_TEST_EXPECT_MSG_EQ(m_expectedAid, m_staDevices.GetN(), "Not all STAs completed association"); + NS_TEST_EXPECT_MSG_EQ(m_expectedAid, + m_startAid + m_staDevices.GetN() - 1, + "Not all STAs completed association"); for (uint32_t i = 0; i < m_staDevices.GetN(); ++i) { @@ -432,6 +436,7 @@ MultiLinkOperationsTestBase::MultiLinkOperationsTestBase(const std::string& name m_assocType(baseParams.assocType), m_staMacs(nStations), m_nStations(nStations), + m_startAid(1), m_lastAid(0), m_rxPkts(nStations + 1) { @@ -780,6 +785,8 @@ MultiLinkOperationsTestBase::DoSetup() m_apMac->TraceConnectWithoutContext("AssociatedSta", MakeCallback(&MultiLinkOperationsTestBase::SetSsid, this)); m_staMacs[0]->SetSsid(Ssid("ns-3-ssid")); + + m_startAid = m_apMac->GetNextAssociationId(); } Ptr @@ -812,9 +819,9 @@ MultiLinkOperationsTestBase::SetSsid(uint16_t aid, Mac48Address /* addr */) m_lastAid = aid; // make the next STA to start ML discovery & setup - if (aid < m_nStations) + if (const std::size_t count = aid - m_startAid + 1; count < m_nStations) { - m_staMacs[aid]->SetSsid(Ssid("ns-3-ssid")); + m_staMacs[count]->SetSsid(Ssid("ns-3-ssid")); return; } // stop generation of beacon frames in order to avoid interference diff --git a/src/wifi/test/wifi-mlo-test.h b/src/wifi/test/wifi-mlo-test.h index c070fdc6f..d13b6417e 100644 --- a/src/wifi/test/wifi-mlo-test.h +++ b/src/wifi/test/wifi-mlo-test.h @@ -169,6 +169,7 @@ class AidAssignmentTest : public TestCase const std::vector> m_linkIds; //!< link IDs for all non-AP STAs/MLDs WifiAssocType m_assocType; //!< association type NetDeviceContainer m_staDevices; //!< non-AP STAs/MLDs devices + uint16_t m_startAid; //!< first AID to allocate to stations uint16_t m_expectedAid; //!< expected AID for current non-AP STA/MLD }; @@ -302,6 +303,7 @@ class MultiLinkOperationsTestBase : public TestCase Ptr m_apMac; ///< AP wifi MAC std::vector> m_staMacs; ///< STA wifi MACs uint8_t m_nStations; ///< number of stations to create + uint16_t m_startAid; ///< first AID to allocate to stations uint16_t m_lastAid; ///< AID of last associated station Time m_duration{Seconds(1)}; ///< simulation duration std::vector m_rxPkts; ///< number of packets received at application layer