diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 1f56540c5..99bb5f131 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -629,6 +629,7 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) const auto& mle = std::visit([](auto&& frame) { return frame.template Get(); }, bestAp->m_frame); + std::map swapInfo; for (const auto& [localLinkId, apLinkId, bssid] : bestAp->m_setupLinks) { NS_ASSERT_MSG(mle, "We get here only for ML setup"); @@ -641,7 +642,11 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) mleCommonInfo = std::make_shared(mle->GetCommonInfoBasic()); } GetWifiRemoteStationManager(localLinkId)->AddStationMleCommonInfo(bssid, mleCommonInfo); + swapInfo.emplace(localLinkId, apLinkId); } + + SwapLinks(swapInfo); + // lambda to get beacon interval from Beacon or Probe Response auto getBeaconInterval = [](auto&& frame) { using T = std::decay_t; diff --git a/src/wifi/model/wifi-mac-queue-scheduler-impl.h b/src/wifi/model/wifi-mac-queue-scheduler-impl.h index f88dc65c5..e8d83aa7d 100644 --- a/src/wifi/model/wifi-mac-queue-scheduler-impl.h +++ b/src/wifi/model/wifi-mac-queue-scheduler-impl.h @@ -352,16 +352,15 @@ WifiMacQueueSchedulerImpl::InitQueueInfo(AcIndex ac, PtrGetMldAddress(rxAddr), + NS_ASSERT_MSG(rxAddr.IsGroup() || GetMac()->GetMldAddress(rxAddr) == rxAddr, "Address 1 (" << rxAddr << ") is not an MLD address"); // this assert checks that association (ML setup) has been established // between sender and receiver (unless the receiver is the broadcast address) NS_ASSERT_MSG(GetMac()->CanForwardPacketsTo(rxAddr), "Cannot forward frame to " << rxAddr); - // we have to include all the links in case of broadcast frame (we are an AP) // and the links that have been setup with the receiver in case of unicast frame - for (uint8_t linkId = 0; linkId < GetMac()->GetNLinks(); linkId++) + for (const auto linkId : GetMac()->GetLinkIds()) { if (rxAddr.IsGroup() || GetMac()->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(rxAddr)) diff --git a/src/wifi/model/wifi-net-device.cc b/src/wifi/model/wifi-net-device.cc index 484fca34e..08dbc9dc2 100644 --- a/src/wifi/model/wifi-net-device.cc +++ b/src/wifi/model/wifi-net-device.cc @@ -394,7 +394,7 @@ WifiNetDevice::GetAddress() const if (m_mac->GetTypeOfStation() == STA && (staMac = StaticCast(m_mac))->IsAssociated() && m_mac->GetNLinks() > 1 && (linkIds = staMac->GetSetupLinkIds()).size() == 1 && - !GetRemoteStationManager(*linkIds.begin()) + !m_mac->GetWifiRemoteStationManager(*linkIds.begin()) ->GetMldAddress(m_mac->GetBssid(*linkIds.begin()))) { return m_mac->GetFrameExchangeManager(*linkIds.begin())->GetAddress(); diff --git a/src/wifi/test/wifi-mlo-test.cc b/src/wifi/test/wifi-mlo-test.cc index 9eb20a309..136e08c20 100644 --- a/src/wifi/test/wifi-mlo-test.cc +++ b/src/wifi/test/wifi-mlo-test.cc @@ -712,13 +712,14 @@ class MultiLinkSetupTest : public MultiLinkOperationsTestBase * \param staChannels the strings specifying the operating channels for the STA * \param apChannels the strings specifying the operating channels for the AP * \param scanType the scan type (active or passive) - * \param setupLinks a list of links (STA link ID, AP link ID) that are expected to be setup + * \param setupLinks a list of links that are expected to be setup. In case one of the two + * devices has a single link, the ID of the link on the MLD is indicated * \param fixedPhyBands list of IDs of STA links that cannot switch PHY band */ MultiLinkSetupTest(std::vector staChannels, std::vector apChannels, WifiScanType scanType, - std::vector> setupLinks, + std::vector setupLinks, std::vector fixedPhyBands = {}); ~MultiLinkSetupTest() override = default; @@ -770,7 +771,7 @@ class MultiLinkSetupTest : public MultiLinkOperationsTestBase void CheckAssocResponse(Ptr mpdu, uint8_t linkId); /// expected links to setup (STA link ID, AP link ID) - const std::vector> m_setupLinks; + const std::vector m_setupLinks; WifiScanType m_scanType; //!< the scan type (active or passive) std::size_t m_nProbeResp; //!< number of Probe Responses received by the non-AP MLD }; @@ -778,7 +779,7 @@ class MultiLinkSetupTest : public MultiLinkOperationsTestBase MultiLinkSetupTest::MultiLinkSetupTest(std::vector staChannels, std::vector apChannels, WifiScanType scanType, - std::vector> setupLinks, + std::vector setupLinks, std::vector fixedPhyBands) : MultiLinkOperationsTestBase("Check correctness of Multi-Link Setup", 1, @@ -1027,14 +1028,12 @@ MultiLinkSetupTest::CheckAssocRequest(Ptr mpdu, uint8_t linkId) +staLinkId.value(), +linkId, "The STA that sent the Assoc Request should not be included in a Per-STA Profile"); - auto it = std::find_if(m_setupLinks.begin(), m_setupLinks.end(), [&staLinkId](auto&& pair) { - return pair.first == staLinkId.value(); - }); + auto it = std::find(m_setupLinks.begin(), m_setupLinks.end(), staLinkId.value()); NS_TEST_EXPECT_MSG_EQ((it != m_setupLinks.end()), true, "Not expecting to setup STA link ID " << +staLinkId.value()); NS_TEST_EXPECT_MSG_EQ( - +it->second, + +staLinkId.value(), +perStaProfile.GetLinkId(), "Not expecting to request association to AP Link ID in Per-STA Profile"); NS_TEST_EXPECT_MSG_EQ(perStaProfile.HasAssocRequest(), @@ -1093,9 +1092,7 @@ MultiLinkSetupTest::CheckAssocResponse(Ptr mpdu, uint8_t linkId) +apLinkId.value(), +linkId, "The AP that sent the Assoc Response should not be included in a Per-STA Profile"); - auto it = std::find_if(m_setupLinks.begin(), m_setupLinks.end(), [&apLinkId](auto&& pair) { - return pair.second == apLinkId.value(); - }); + auto it = std::find(m_setupLinks.begin(), m_setupLinks.end(), apLinkId.value()); NS_TEST_EXPECT_MSG_EQ((it != m_setupLinks.end()), true, "Not expecting to setup AP link ID " << +apLinkId.value()); @@ -1113,8 +1110,11 @@ MultiLinkSetupTest::CheckMlSetup() */ NS_TEST_EXPECT_MSG_EQ(m_staMacs[0]->IsAssociated(), true, "Expected the STA to be associated"); - for (const auto& [staLinkId, apLinkId] : m_setupLinks) + for (const auto linkId : m_setupLinks) { + auto staLinkId = (m_staMacs[0]->GetNLinks() > 1 ? linkId : SINGLE_LINK_OP_ID); + auto apLinkId = (m_apMac->GetNLinks() > 1 ? linkId : SINGLE_LINK_OP_ID); + auto staAddr = m_staMacs[0]->GetFrameExchangeManager(staLinkId)->GetAddress(); auto apAddr = m_apMac->GetFrameExchangeManager(apLinkId)->GetAddress(); @@ -1184,11 +1184,15 @@ MultiLinkSetupTest::CheckMlSetup() void MultiLinkSetupTest::CheckDisabledLinks() { - for (std::size_t linkId = 0; linkId < m_staChannels.size(); linkId++) + if (m_staMacs[0]->GetNLinks() == 1) { - auto it = std::find_if(m_setupLinks.begin(), m_setupLinks.end(), [&linkId](auto&& link) { - return link.first == linkId; - }); + // no link is disabled on a single link device + return; + } + + for (const auto& linkId : m_staMacs[0]->GetLinkIds()) + { + auto it = std::find(m_setupLinks.begin(), m_setupLinks.end(), linkId); if (it == m_setupLinks.end()) { // the link has not been setup @@ -2743,12 +2747,10 @@ class WifiMultiLinkOperationsTestSuite : public TestSuite WifiMultiLinkOperationsTestSuite::WifiMultiLinkOperationsTestSuite() : TestSuite("wifi-mlo", UNIT) { - using ParamsTuple = - std::tuple, // non-AP MLD channels - std::vector, // AP MLD channels - std::vector>, // (STA link ID, AP link ID) of setup - // links - std::vector>; // IDs of link that cannot change PHY band + using ParamsTuple = std::tuple, // non-AP MLD channels + std::vector, // AP MLD channels + std::vector, // link ID of setup links + std::vector>; // IDs of link that cannot change PHY band AddTestCase(new GetRnrLinkInfoTest(), TestCase::QUICK); AddTestCase(new MldSwapLinksTest(), TestCase::QUICK); @@ -2757,24 +2759,24 @@ WifiMultiLinkOperationsTestSuite::WifiMultiLinkOperationsTestSuite() {// matching channels: setup all links ParamsTuple({"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"}, - {{0, 0}, {1, 1}, {2, 2}}, + {0, 1, 2}, {}), // non-matching channels, matching PHY bands: setup all links ParamsTuple({"{108, 0, BAND_5GHZ, 0}", "{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{120, 0, BAND_5GHZ, 0}", "{5, 0, BAND_6GHZ, 0}"}, - {{1, 0}, {0, 1}, {2, 2}}, + {0, 1, 2}, {}), // non-AP MLD switches band on some links to setup 3 links ParamsTuple({"{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{36, 0, BAND_5GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{9, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{2, 0}, {0, 1}, {1, 2}}, + {0, 1, 2}, {}), // the first link of the non-AP MLD cannot change PHY band and no AP is operating on // that band, hence only 2 links are setup ParamsTuple( {"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}", "{8, 20, BAND_2_4GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{1, 0}, {2, 1}}, + {0, 1}, {0}), // the first link of the non-AP MLD cannot change PHY band and no AP is operating on // that band; the second link of the non-AP MLD cannot change PHY band and there is @@ -2782,7 +2784,7 @@ WifiMultiLinkOperationsTestSuite::WifiMultiLinkOperationsTestSuite() ParamsTuple( {"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}", "{8, 20, BAND_2_4GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{1, 0}, {2, 1}}, + {0, 1}, {0, 1}), // the first link of the non-AP MLD cannot change PHY band and no AP is operating on // that band; the second link of the non-AP MLD cannot change PHY band and there is @@ -2791,29 +2793,29 @@ WifiMultiLinkOperationsTestSuite::WifiMultiLinkOperationsTestSuite() // hence 2 links are setup by switching channel (not band) on the third link ParamsTuple({"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}", "{60, 0, BAND_5GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{1, 0}, {2, 2}}, + {0, 2}, {0, 1, 2}), // the first link of the non-AP MLD cannot change PHY band and no AP is operating on // that band; the second link of the non-AP MLD cannot change PHY band and there is // an AP operating on the same channel; hence one link only is setup - ParamsTuple({"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}"}, + ParamsTuple({"{2, 0, BAND_2_4GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{1, 0}}, + {2}, {0, 1}), // non-AP MLD has only two STAs and setups two links ParamsTuple({"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{0, 1}, {1, 0}}, + {1, 0}, {}), // single link non-AP STA associates with an AP affiliated with an AP MLD ParamsTuple({"{120, 0, BAND_5GHZ, 0}"}, {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, - {{0, 2}}, + {2}, // link ID of AP MLD only (non-AP STA is single link) {}), // a STA affiliated with a non-AP MLD associates with a single link AP ParamsTuple({"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}", "{120, 0, BAND_5GHZ, 0}"}, {"{120, 0, BAND_5GHZ, 0}"}, - {{2, 0}}, + {2}, // link ID of non-AP MLD only (AP is single link) {})}) { AddTestCase(new MultiLinkSetupTest(staChannels,