102 auto linkId = mac->GetLinkForPhy(phyId);
109 for (
const auto& [aid, psdu] : psduMap)
111 std::stringstream ss;
112 ss << std::setprecision(10) <<
"PSDU #" <<
m_txPsdus.size() <<
" Link ID "
113 << +linkId.value() <<
" Phy ID " << +phyId <<
" " << psdu->GetHeader(0).GetTypeString();
114 if (psdu->GetHeader(0).IsAction())
118 psdu->GetPayload(0)->PeekHeader(actionHdr);
121 ss <<
" #MPDUs " << psdu->GetNMpdus() <<
" duration/ID " << psdu->GetHeader(0).GetDuration()
122 <<
" RA = " << psdu->GetAddr1() <<
" TA = " << psdu->GetAddr2()
123 <<
" ADDR3 = " << psdu->GetHeader(0).GetAddr3()
124 <<
" ToDS = " << psdu->GetHeader(0).IsToDs()
125 <<
" FromDS = " << psdu->GetHeader(0).IsFromDs();
126 if (psdu->GetHeader(0).IsQosData())
131 ss << mpdu->GetHeader().GetSequenceNumber() <<
",";
133 ss <<
"} TID = " << +psdu->GetHeader(0).GetQosTid();
141 staMac && staMac->IsEmlsrLink(*linkId) &&
142 staMac->GetEmlsrManager()->GetMediumSyncDuration().IsStrictlyPositive())
144 const auto mustStartMsd =
145 staMac->GetEmlsrManager()->GetInDeviceInterference() &&
148 for (
auto id : staMac->GetLinkIds())
152 if (!staMac->IsEmlsrLink(
id) ||
id == *linkId || staMac->GetWifiPhy(
id) ==
nullptr)
157 txDuration - TimeStep(1),
158 [=, hdrType = psdu->GetHeader(0).GetTypeString(),
this]() {
160 bool msdWasRunning = staMac->GetEmlsrManager()
161 ->GetElapsedMediumSyncDelayTimer(id)
163 if (auto phy = staMac->GetWifiPhy(id);
164 !msdWasRunning && !mustStartMsd && phy && phy->IsStateSleep())
176 (msdWasRunning || mustStartMsd),
177 std::string(
"after transmitting ") + hdrType +
178 " on link " + std::to_string(*linkId));
184 NS_LOG_INFO(
"TX duration = " << txDuration.As(
Time::MS) <<
" TXVECTOR = " << txVector <<
"\n");
304 int64_t streamNumber = 100;
316 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
321 wifi.ConfigEhtOptions(
"EmlsrActivated",
330 phyHelper.
Set(0,
"ChannelSettings",
StringValue(
"{2, 0, BAND_2_4GHZ, 0}"));
331 phyHelper.
Set(1,
"ChannelSettings",
StringValue(
"{36, 0, BAND_5GHZ, 0}"));
332 phyHelper.
Set(2,
"ChannelSettings",
StringValue(
"{1, 0, BAND_6GHZ, 0}"));
339 mac.SetType(
"ns3::ApWifiMac",
344 mac.SetApEmlsrManager(
"ns3::AdvancedApEmlsrManager",
345 "WaitTransDelayOnPsduRxError",
350 mac.SetType(
"ns3::StaWifiMac",
357 mac.SetEmlsrManager(
"ns3::AdvancedEmlsrManager",
367 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
371 auto emlsrManager = staMac->GetEmlsrManager();
376 emlsrManager->TraceConnectWithoutContext(
384 wifi.ConfigEhtOptions(
"EmlsrActivated",
BooleanValue(
false));
386 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
387 wifiStaNodes.Add(otherStaNodes);
390 for (
uint32_t i = 0; i < staDevices.GetN(); i++)
397 for (uint8_t phyId = 0; phyId <
m_apMac->GetDevice()->GetNPhys(); phyId++)
400 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
406 for (uint8_t phyId = 0; phyId <
m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
409 "/NodeList/" + std::to_string(i + 1) +
"/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
410 std::to_string(phyId) +
"/PhyTxPsduBegin",
429 positionAlloc->Add(Vector(std::min<double>(
id, 1), 0.0, 0.0));
431 mobility.SetPositionAllocator(positionAlloc);
433 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
434 mobility.Install(wifiApNode);
435 mobility.Install(wifiStaNodes);
439 packetSocket.
Install(wifiApNode);
440 packetSocket.
Install(wifiStaNodes);
452 server->SetLocal(srvAddr);
453 (*nodeIt)->AddApplication(server);
454 server->SetStartTime(
Seconds(0));
463 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
467 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
473 m_apMac->TraceConnectWithoutContext(
"AssociatedSta",
1086 auto jumpToQosDataOrMuRts = [&]() {
1088 !psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData())
1090 auto psdu = psduIt->psduMap.cbegin()->second;
1091 if (psdu->GetHeader(0).IsTrigger())
1094 psdu->GetPayload(0)->PeekHeader(trigger);
1158 std::set<uint8_t> linkIds;
1160 jumpToQosDataOrMuRts();
1162 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData()),
1164 "Expected at least one QoS data frame before enabling EMLSR mode");
1165 linkIds.insert(psduIt->linkId);
1166 const auto firstAmpduTxEnd =
1170 m_staMacs[i]->GetWifiPhy(psduIt->linkId)->GetPhyBand());
1173 jumpToQosDataOrMuRts();
1175 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData()),
1177 "Expected at least two QoS data frames before enabling EMLSR mode");
1178 linkIds.insert(psduIt->linkId);
1179 const auto secondAmpduTxStart = psduIt->startTx;
1187 auto setupLinks =
m_staMacs[i]->GetSetupLinkIds();
1189 std::none_of(setupLinks.begin(), setupLinks.end(), [&](
auto&& linkId) {
1190 return linkId != m_mainPhyId && m_emlsrLinks.count(linkId) == 0;
1195 "Expected both A-MPDUs to be sent on the same link");
1199 "A-MPDUs are not sent one after another");
1209 "Expected A-MPDUs to be sent on distinct links");
1212 "A-MPDUs are not sent concurrently");
1278 using FrameExchange = std::list<
decltype(psduIt)>;
1285 jumpToQosDataOrMuRts();
1294 psduIt->psduMap.cbegin()->second->GetPayload(0)->PeekHeader(trigger);
1299 "jumpToQosDataOrMuRts does not return TFs other than MU-RTS");
1300 for (
const auto& userInfo : trigger)
1304 if (
m_staMacs.at(i)->GetAssociationId() == userInfo.GetAid12())
1306 frameExchanges.at(i).emplace_back(FrameExchange{psduIt});
1318 for (
const auto& staIdPsduPair : psduIt->psduMap)
1321 if (!staMac->GetLinkIdByAddress(staIdPsduPair.second->GetAddr1()))
1329 std::size_t
id = staMac->GetDevice()->GetNode()->GetId() - 1;
1330 for (
auto& frameExchange : frameExchanges.at(
id))
1332 if (
IsTrigger(frameExchange.front()->psduMap) &&
1333 frameExchange.front()->linkId == psduIt->linkId &&
1334 frameExchange.size() == 1)
1336 auto it = std::next(frameExchange.front());
1340 if (it->linkId == psduIt->linkId &&
1341 !it->psduMap.begin()->second->GetHeader(0).IsCts())
1350 frameExchange.emplace_back(psduIt);
1355 frameExchanges.at(
id).emplace_back(FrameExchange{psduIt});
1367 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1371 "Expected at least 2 frame exchange sequences "
1372 <<
"involving EMLSR client " << i);
1374 auto firstExchangeIt = frameExchanges.at(i).begin();
1375 auto secondExchangeIt = std::next(firstExchangeIt);
1377 const auto firstAmpduTxEnd =
1378 firstExchangeIt->back()->startTx +
1380 firstExchangeIt->back()->psduMap,
1381 firstExchangeIt->back()->txVector,
1382 m_staMacs[i]->GetWifiPhy(firstExchangeIt->back()->linkId)->GetPhyBand());
1383 const auto secondAmpduTxStart = secondExchangeIt->front()->startTx;
1385 if (m_staMacs[i]->GetNLinks() == m_emlsrLinks.size())
1390 "Expected an MU-RTS TF as ICF of first frame exchange sequence");
1392 firstExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1394 "Expected a QoS data frame in the first frame exchange sequence");
1398 "Expected an MU-RTS TF as ICF of second frame exchange sequence");
1400 secondExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1402 "Expected a QoS data frame in the second frame exchange sequence");
1406 "A-MPDUs are not sent one after another");
1410 std::vector<uint8_t> nonEmlsrIds;
1411 auto setupLinks = m_staMacs[i]->GetSetupLinkIds();
1412 std::set_difference(setupLinks.begin(),
1414 m_emlsrLinks.begin(),
1416 std::back_inserter(nonEmlsrIds));
1419 auto nonEmlsrLinkExchangeIt = firstExchangeIt->front()->linkId == nonEmlsrIds[0]
1424 "Did not expect an MU-RTS TF as ICF on non-EMLSR link");
1426 nonEmlsrLinkExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1428 "Expected a QoS data frame on the non-EMLSR link");
1430 auto emlsrLinkExchangeIt =
1431 nonEmlsrLinkExchangeIt == firstExchangeIt ? secondExchangeIt : firstExchangeIt;
1434 "Expected this exchange not to occur on non-EMLSR link");
1437 "Expected an MU-RTS TF as ICF on the EMLSR link");
1439 emlsrLinkExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1441 "Expected a QoS data frame on the EMLSR link");
1445 "A-MPDUs are not sent concurrently");
1449 frameExchanges.at(i).erase(firstExchangeIt);
1450 frameExchanges.at(i).erase(secondExchangeIt);
1478 if (m_nEmlsrStations == 2 && m_apMac->GetNLinks() == m_emlsrLinks.size())
1481 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1485 "Expected at least 2 frame exchange sequences "
1486 <<
"involving EMLSR client " << i);
1488 auto firstExchangeIt = frameExchanges.at(i).begin();
1492 "Expected an MU-RTS TF as ICF of first frame exchange sequence");
1494 firstExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1496 "Expected a QoS data frame in the first frame exchange sequence");
1500 auto secondExchangeIt = std::next(frameExchanges.at(0).begin())->front()->startTx <
1501 std::next(frameExchanges.at(1).begin())->front()->startTx
1502 ? std::next(frameExchanges.at(0).begin())
1503 :
std::next(frameExchanges.at(1).begin());
1504 decltype(secondExchangeIt) thirdExchangeIt;
1505 std::size_t thirdExchangeStaId;
1507 if (secondExchangeIt == std::next(frameExchanges.at(0).begin()))
1509 thirdExchangeIt = std::next(frameExchanges.at(1).begin());
1510 thirdExchangeStaId = 1;
1514 thirdExchangeIt = std::next(frameExchanges.at(0).begin());
1515 thirdExchangeStaId = 0;
1522 "Expected no ICF for the second frame exchange sequence");
1524 secondExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1526 "Expected a QoS data frame in the second frame exchange sequence");
1530 +frameExchanges.at(0).begin()->front()->linkId,
1531 "Expected the first two frame exchanges to occur on the same link");
1533 auto bAckRespIt = std::prev(secondExchangeIt->front());
1536 "Expected a BlockAck response before the second frame exchange");
1537 auto bAckRespTxEnd =
1538 bAckRespIt->startTx +
1540 bAckRespIt->txVector,
1541 m_apMac->GetWifiPhy(bAckRespIt->linkId)->GetPhyBand());
1545 bAckRespTxEnd + m_apMac->GetWifiPhy(bAckRespIt->linkId)->GetSifs(),
1546 secondExchangeIt->front()->startTx,
1547 "Expected the second frame exchange to start a SIFS after the first one");
1552 "Expected an MU-RTS as ICF for the third frame exchange sequence");
1554 thirdExchangeIt->back()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1556 "Expected a QoS data frame in the third frame exchange sequence");
1559 +secondExchangeIt->front()->linkId,
1560 +thirdExchangeIt->front()->linkId,
1561 "Expected the second and third frame exchanges to occur on distinct links");
1563 auto secondQosIt = secondExchangeIt->front();
1564 auto secondQosTxEnd =
1565 secondQosIt->startTx +
1567 secondQosIt->txVector,
1568 m_apMac->GetWifiPhy(secondQosIt->linkId)->GetPhyBand());
1571 secondQosTxEnd + m_transitionDelay.at(thirdExchangeStaId),
1572 "Transmission started before transition delay");
1578 "Expected a fourth frame exchange");
1579 auto fourthExchangeIt = std::next(thirdExchangeIt);
1584 "Expected an MU-RTS as ICF for the fourth frame exchange sequence");
1586 bAckRespIt = std::prev(fourthExchangeIt->front());
1589 "Expected a BlockAck response before the fourth frame exchange");
1590 auto phy = m_apMac->GetWifiPhy(bAckRespIt->linkId);
1592 bAckRespIt->txVector,
1600 bAckRespTxEnd +
phy->GetPifs(),
1601 "Transmission started less than a PIFS after BlockAck");
1603 bAckRespTxEnd +
phy->GetPifs() +
1605 "Transmission started too much time after BlockAck");
1607 auto bAckReqIt = std::next(fourthExchangeIt->front(), 2);
1610 "Expected a BlockAck request in the fourth frame exchange");
1614 frameExchanges.at(0).pop_front();
1615 frameExchanges.at(0).pop_front();
1616 frameExchanges.at(1).pop_front();
1617 frameExchanges.at(1).pop_front();
1618 frameExchanges.at(thirdExchangeStaId).pop_front();
1680 for (std::size_t i = 0; i < m_nEmlsrStations; i++)
1685 auto exchangeIt = frameExchanges.at(i).cbegin();
1687 auto linkIdOpt = m_staMacs[i]->GetLinkForPhy(m_mainPhyId);
1690 "Didn't find a link on which the main PHY is operating");
1692 if (
IsTrigger(exchangeIt->front()->psduMap))
1696 "ICF was not sent on the expected link");
1699 "Expected no data frame in the first frame exchange sequence");
1700 frameExchanges.at(i).pop_front();
1705 "Expected at least 2 frame exchange sequences "
1706 <<
"involving EMLSR client " << i);
1708 auto firstExchangeIt = frameExchanges.at(i).cbegin();
1709 auto secondExchangeIt = std::next(firstExchangeIt);
1711 const auto firstAmpduTxEnd =
1712 firstExchangeIt->back()->startTx +
1714 firstExchangeIt->back()->psduMap,
1715 firstExchangeIt->back()->txVector,
1716 m_staMacs[i]->GetWifiPhy(firstExchangeIt->back()->linkId)->GetPhyBand());
1717 const auto secondAmpduTxStart = secondExchangeIt->front()->startTx;
1720 firstExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1722 "Expected a QoS data frame in the first frame exchange sequence");
1725 "Expected one frame only in the first frame exchange sequence");
1728 secondExchangeIt->front()->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
1730 "Expected a QoS data frame in the second frame exchange sequence");
1733 "Expected one frame only in the second frame exchange sequence");
1735 if (m_staMacs[i]->GetNLinks() == m_emlsrLinks.size())
1740 +firstExchangeIt->front()->linkId,
1742 "First frame exchange expected to occur on link used to send EML OMN");
1745 +secondExchangeIt->front()->linkId,
1747 "Second frame exchange expected to occur on link used to send EML OMN");
1751 "A-MPDUs are not sent one after another");
1757 +secondExchangeIt->front()->linkId,
1758 "Frame exchanges expected to occur on distinct links");
1762 "A-MPDUs are not sent concurrently");
1906 auto pkt = mpdu->GetPacket()->Copy();
1907 const auto& hdr = mpdu->GetHeader();
1910 pkt->RemoveHeader(frame);
1912 std::optional<std::size_t> staId;
1915 if (
m_staMacs.at(
id)->GetFrameExchangeManager(linkId)->GetAddress() == hdr.GetAddr2())
1923 "Not an address of an EMLSR client " << hdr.GetAddr1());
1925 auto phy =
m_staMacs.at(*staId)->GetWifiPhy(linkId);
1928 m_apMac->GetWifiRemoteStationManager(linkId)->GetAckTxVector(hdr.GetAddr2(), txVector);
1932 m_staMacs.at(*staId)->GetWifiRemoteStationManager(linkId)->GetRtsTxVector(
1943 auto timeToCfEnd = txDuration + phy->GetSifs() + ackDuration + phy->GetSifs() + cfEndDuration;
1948 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
1953 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
1954 id != linkId &&
m_staMacs.at(*staId)->IsEmlsrLink(
id),
1955 "Checking links on EMLSR client " + std::to_string(*staId) +
1956 " before the end of CF-End frame");
1960 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
1961 id != linkId &&
m_staMacs.at(*staId)->IsEmlsrLink(
id),
1962 "Checking links of EMLSR client " + std::to_string(*staId) +
1963 " on the AP MLD before the end of CF-End frame");
1969 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
1971 if (
m_staMacs.at(*staId)->IsEmlsrLink(
id))
1975 m_staMacs.at(*staId)->GetAddress(),
1976 id && m_staMacs.at(*staId)->IsEmlsrLink(id),
1977 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
1979 "Checking links of EMLSR client " + std::to_string(*staId) +
1980 " are all blocked on the AP MLD right after the end of CF-End");
1987 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
1989 if (
m_staMacs.at(*staId)->IsEmlsrLink(
id))
1991 CheckBlockedLink(m_apMac,
1992 m_staMacs.at(*staId)->GetAddress(),
1994 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
1996 "Checking links of EMLSR client " + std::to_string(*staId) +
1997 " are all blocked on the AP MLD before the end of "
1998 "transition delay");
2004 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2006 if (
m_staMacs.at(*staId)->IsEmlsrLink(
id))
2008 CheckBlockedLink(m_apMac,
2009 m_staMacs.at(*staId)->GetAddress(),
2011 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2013 "Checking links of EMLSR client " + std::to_string(*staId) +
2014 " are all unblocked on the AP MLD after the transition delay");
2164 std::size_t firstClientId = 0;
2165 std::size_t secondClientId = 1;
2166 auto addr =
m_staMacs[secondClientId]->GetAddress();
2176 m_apMac->GetDevice()->GetNode()->AddApplication(
2179 for (std::size_t clientId : {firstClientId, secondClientId})
2182 for (uint8_t
id = 0;
id <
m_staMacs[clientId]->GetNLinks();
id++)
2188 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2190 "Checking EMLSR links on EMLSR client " +
2191 std::to_string(clientId) +
2192 " after receiving the first QoS data frame");
2199 m_apMac->GetDevice()->GetNode()->AddApplication(
2204 for (std::size_t clientId : {firstClientId, secondClientId})
2206 for (uint8_t
id = 0;
id <
m_staMacs[clientId]->GetNLinks();
id++)
2212 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2214 "Checking EMLSR links on EMLSR client " +
2215 std::to_string(clientId) +
2216 " when starting the reception of the second QoS frame");
2227 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2232 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2234 "Checking that links of EMLSR client " +
2235 std::to_string(secondClientId) +
2236 " are blocked on the AP MLD before the end of the PPDU");
2243 for (uint8_t
id = 0;
id <
m_staMacs[secondClientId]->GetNLinks();
id++)
2248 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2250 "Checking that links of EMLSR client " +
2251 std::to_string(secondClientId) +
2252 " are unblocked before the end of the second QoS frame");
2257 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2262 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2264 "Checking links of EMLSR client " +
2265 std::to_string(secondClientId) +
2266 " are all blocked on the AP MLD after the end of the PPDU");
2273 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2279 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2281 "Checking links of EMLSR client " + std::to_string(secondClientId) +
2282 " are all blocked on the AP MLD before the transition delay",
2296 m_apMac->GetDevice()->GetNode()->AddApplication(
2306 psduMap.cbegin()->second->GetAddr1(),
2308 "QoS frame not addressed to a non-EMLSR client");
2310 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2315 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2317 "Checking links of EMLSR client " + std::to_string(secondClientId) +
2318 " are all blocked on the AP MLD before the transition delay");
2323 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2327 m_apMac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED, addr, {
id});
2333 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2335 m_apMac->UnblockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED, addr, {
id});
2340 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2345 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2347 "Checking EMLSR links on EMLSR client " +
2348 std::to_string(secondClientId) +
2349 " after receiving the fourth QoS data frame");
2374 auto taddr = psduMap.cbegin()->second->GetAddr2();
2375 std::size_t clientId;
2376 if (
m_staMacs[0]->GetLinkIdByAddress(taddr))
2384 "Unexpected TA for BlockAck: " << taddr);
2389 auto currMainPhyLinkId =
m_staMacs[clientId]->GetLinkForPhy(phyId);
2391 currMainPhyLinkId.has_value(),
2393 "Didn't find the link on which the PHY sending the BlockAck is operating");
2394 auto linkId = *currMainPhyLinkId;
2397 auto addr =
m_apMac->GetWifiRemoteStationManager(linkId)->GetMldAddress(taddr);
2400 auto apPhy =
m_apMac->GetWifiPhy(linkId);
2406 apPhy->GetPhyBand());
2419 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2424 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2426 "Checking links on EMLSR client " + std::to_string(clientId) +
2427 " at the end of fourth BlockAck");
2431 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2433 "Checking links of EMLSR client " + std::to_string(clientId) +
2434 " on the AP MLD at the end of fourth BlockAck");
2440 for (uint8_t id = 0; id < m_apMac->GetNLinks(); id++)
2442 CheckBlockedLink(m_staMacs[clientId],
2443 m_apMac->GetAddress(),
2445 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2447 "Checking links on EMLSR client " + std::to_string(clientId) +
2448 " a SIFS after the end of fourth BlockAck");
2449 CheckBlockedLink(m_apMac,
2452 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2454 "Checking links of EMLSR client " + std::to_string(clientId) +
2455 " a SIFS after the end of fourth BlockAck");
2460 auto uid = psduMap.cbegin()->second->GetPacket()->GetUid();
2468 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2473 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2475 "Checking links on EMLSR client " + std::to_string(clientId) +
2476 " at the end of fifth BlockAck");
2480 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2482 "Checking links of EMLSR client " + std::to_string(clientId) +
2483 " on the AP MLD at the end of fifth BlockAck");
2489 txDuration + apPhy->GetSifs() + cfEndTxDuration -
MicroSeconds(1),
2491 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2496 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2498 "Checking links on EMLSR client " + std::to_string(clientId) +
2499 " before the end of CF-End frame");
2503 WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
2505 "Checking links of EMLSR client " + std::to_string(clientId) +
2506 " on the AP MLD before the end of CF-End frame");
2512 txDuration + apPhy->GetSifs() + cfEndTxDuration +
MicroSeconds(1),
2514 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2520 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2522 "Checking links of EMLSR client " + std::to_string(clientId) +
2523 " are all blocked on the AP MLD right after the end of CF-End");
2529 txDuration + apPhy->GetSifs() + cfEndTxDuration +
m_transitionDelay.at(clientId) -
2532 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2538 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2540 "Checking links of EMLSR client " + std::to_string(clientId) +
2541 " are all blocked on the AP MLD before the end of transition delay");
2546 txDuration + apPhy->GetSifs() + cfEndTxDuration +
m_transitionDelay.at(clientId) +
2549 for (uint8_t
id = 0;
id <
m_apMac->GetNLinks();
id++)
2555 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
2557 "Checking links of EMLSR client " + std::to_string(clientId) +
2558 " are all unblocked on the AP MLD after the transition delay");
2976 auto auxPhyLinks =
m_staMacs[0]->GetSetupLinkIds();
3009 traceInfoIt->second->GetName() ==
"TxopEnded")
3011 const auto& traceInfo =
3016 "Expected null remaining time because TXOP ended regularly");
3048 m_staMacs[0]->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
3071 elapsed.has_value(),
3073 "MediumSyncDelay timer not running on link where main PHY is operating");
3075 m_staMacs[0]->GetEmlsrManager()->GetMediumSyncDuration() -
3084 "Backoff end time should have been calculated");
3092 m_staMacs[0]->BlockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
3098 NS_LOG_INFO(
"Enqueuing two packets at the EMLSR client\n");
3109 m_staMacs[0]->GetMacQueueScheduler()->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
3118 m_staMacs[0]->UnblockUnicastTxOnLinks(WifiQueueBlockedReason::TID_NOT_MAPPED,
3123 NS_LOG_INFO(
"Enqueuing two packets at the EMLSR client\n");
3128 m_staMacs[0]->GetEmlsrManager()->SetAuxPhyTxCapable(
false);
3148 "Main PHY is not switching at time "
3154 auto mainPhyLinkid = m_staMacs[0]->GetLinkForPhy(mainPhy);
3157 NS_TEST_EXPECT_MSG_EQ(+mainPhyLinkid.value(),
3159 "Main PHY expected to operate on the preferred link");
3163 NS_TEST_EXPECT_MSG_EQ(
3164 mainPhy->IsStateSwitching(),
3166 "Main PHY is not operating on a link and it is not switching at time "
3167 << Simulator::Now().As(Time::NS));
3175 for (uint8_t
id = 0;
id <
m_staMacs[0]->GetNLinks();
id++)
3183 m_staMacs[0]->GetChannelAccessManager(
id)->GetBackoffEndFor(acBe);
3186 minBackoff = backoff;
3187 slot =
m_staMacs[0]->GetWifiPhy(
id)->GetSlot();
3196 auto expected2ndSwitchDelay =
3207 "Main PHY is not switching at time "
3211 "Main PHY should not be operating on a link because it "
3212 "should be switching to an auxiliary link");
3215 "UlTxopAuxPhyNotTxCapable",
3224 m_staMacs[0]->GetEmlsrManager()->GetAttribute(
"SwitchMainPhyBackDelay",
3225 switchMainPhyBackDelay);
3229 for (uint8_t
id = 0;
id <
m_staMacs[0]->GetNLinks(); ++id)
3235 m_staMacs[0]->GetChannelAccessManager(
id)->NotifyNavStartNow(
3236 2 * switchMainPhyBackDelay.
Get());
3241 CheckMainPhyTraceInfo(0,
3242 "TxopNotGainedOnAuxPhyLink",
3251 auto nonPrimLinkId = m_staMacs[0]->GetLinkForPhy(mainPhy);
3253 NS_TEST_ASSERT_MSG_EQ(nonPrimLinkId.has_value(),
3255 "Main PHY should have completed switching");
3258 ->GetChannelAccessManager(*nonPrimLinkId)
3259 ->NeedBackoffUponAccess(acBe, true, true);
3264 if (auto slots = acBe->GetBackoffSlots(*nonPrimLinkId); slots == 0)
3266 m_5thQosFrameTxTime =
3267 Simulator::Now() + (m_useAuxPhyCca ? Time{0} : mainPhy->GetPifs());
3271 m_5thQosFrameTxTime = m_staMacs[0]
3272 ->GetChannelAccessManager(*nonPrimLinkId)
3273 ->GetBackoffEndFor(acBe);
3281 NS_LOG_INFO(
"Enqueuing two packets at the EMLSR client\n");
3282 m_staMacs[0]->GetDevice()->GetNode()->AddApplication(GetApplication(
UPLINK, 0, 2, 1000));
3417 "Unexpected number of RTS frames sent while the MediumSyncDelay timer is running");
3424 auto jumpToQosDataOrMuRts = [&]() {
3426 !psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData() &&
3427 !psduIt->psduMap.cbegin()->second->GetHeader(0).IsRts())
3429 auto psdu = psduIt->psduMap.cbegin()->second;
3430 if (psdu->GetHeader(0).IsTrigger())
3433 psdu->GetPayload(0)->PeekHeader(trigger);
3520 psduIt->psduMap.cbegin()->second->GetHeader(0).IsBeacon()))
3530 "First QoS data frame has not been transmitted");
3533 "First QoS data frame should be transmitted without protection");
3536 "First QoS data frame should be transmitted by the main PHY");
3539 "First QoS data frame sent too early");
3541 auto prevPsduIt = psduIt++;
3542 jumpToQosDataOrMuRts();
3550 "Expected another QoS data frame sent concurrently with the first frame");
3552 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData(),
3554 "First data frame on non-EMLSR link should be transmitted without protection");
3557 "First data frame expected to be transmitted on the non-EMLSR link");
3558 const auto txDuration =
3560 prevPsduIt->txVector,
3561 m_staMacs[0]->GetWifiPhy(prevPsduIt->phyId)->GetPhyBand());
3563 prevPsduIt->startTx + txDuration,
3564 "First data frame on the non-EMLSR link not sent concurrently");
3566 jumpToQosDataOrMuRts();
3574 "RTS before second QoS data frame has not been transmitted");
3577 "Second QoS data frame should be transmitted with protection");
3581 "RTS before second QoS data frame should not be transmitted by the main PHY");
3584 "RTS before second data frame transmitted on an unexpected width");
3589 "CTS before second QoS data frame has not been transmitted");
3592 "CTS before second QoS data frame has not been transmitted");
3597 "Second QoS data frame has not been transmitted");
3600 "Second QoS data frame has not been transmitted");
3603 "Second QoS data frame should be transmitted by the main PHY");
3606 "Second data frame not transmitted on the same width as RTS");
3608 bool moreQosDataFound =
false;
3612 jumpToQosDataOrMuRts();
3614 psduIt->psduMap.cbegin()->second->GetHeader(0).IsQosData())
3616 moreQosDataFound =
true;
3620 "Third QoS data frame should be transmitted by the main PHY");
3623 "Expecting TX width of third data frame to equal the channel "
3624 "width used by the main PHY");
3628 "Third QoS data frame sent before MediumSyncDelay timer expired");
3636 "Third QoS data frame transmitted by the main PHY not found");
3640 jumpToQosDataOrMuRts();
3646 "RTS before fourth QoS data frame has not been transmitted");
3649 "Fourth QoS data frame should be transmitted with protection");
3653 "RTS before fourth QoS data frame should not be transmitted by the main PHY");
3656 "RTS before fourth data frame transmitted on an unexpected width");
3661 "CTS before fourth QoS data frame has not been transmitted");
3664 "CTS before fourth QoS data frame has not been transmitted");
3666 jumpToQosDataOrMuRts();
3673 "RTS before fourth QoS data frame has not been transmitted");
3676 "Fourth QoS data frame should be transmitted with protection");
3680 "RTS before fourth QoS data frame should not be transmitted by the main PHY");
3683 "RTS before fourth data frame transmitted on an unexpected width");
3688 "CTS before fourth QoS data frame has not been transmitted");
3691 "CTS before fourth QoS data frame has not been transmitted");
3696 "Fourth QoS data frame has not been transmitted");
3699 "Fourth QoS data frame has not been transmitted");
3702 "Fourth QoS data frame should be transmitted by the main PHY");
3705 "Fourth data frame not transmitted on the same width as RTS");
3707 auto fourthLinkId = psduIt->linkId;
3710 jumpToQosDataOrMuRts();
3721 "Fifth data frame transmitted too late");
3724 psduIt->txVector.GetChannelWidth(),
3726 "Fifth data frame not transmitted on the correct channel width");
3731 if (psduIt->linkId != fourthLinkId)
3736 "Fifth QoS data frame should be transmitted with protection");
3740 "RTS before fifth QoS data frame should be transmitted by the main PHY");
3745 "CTS before fifth QoS data frame has not been transmitted");
3748 "CTS before fifth QoS data frame has not been transmitted");
3755 "Fifth QoS data frame has not been transmitted");
3758 "Fifth QoS data frame has not been transmitted");
3761 "Fifth QoS data frame should be transmitted by the main PHY");
3764 "Fifth QoS data frame should be transmitted on an auxiliary link");
3766 psduIt->txVector.GetChannelWidth(),
3768 "Fifth data frame not transmitted on the correct channel width");