26 #include "ns3/abort.h"
27 #include "ns3/ap-wifi-mac.h"
28 #include "ns3/erp-ofdm-phy.h"
30 #include "ns3/recipient-block-ack-agreement.h"
31 #include "ns3/snr-tag.h"
32 #include "ns3/sta-wifi-mac.h"
33 #include "ns3/wifi-mac-queue.h"
34 #include "ns3/wifi-mac-trailer.h"
39 #undef NS_LOG_APPEND_CONTEXT
40 #define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
52 return psduMap.size() == 1 && psduMap.cbegin()->first ==
SU_STA_ID &&
53 psduMap.cbegin()->second->GetNMpdus() == 1 &&
54 psduMap.cbegin()->second->GetHeader(0).IsTrigger();
60 static TypeId tid =
TypeId(
"ns3::HeFrameExchangeManager")
62 .AddConstructor<HeFrameExchangeManager>()
63 .SetGroupName(
"Wifi");
68 : m_intraBssNavEnd(0),
69 m_triggerFrameInAmpdu(false)
116 phy->TraceConnectWithoutContext(
"PhyRxPayloadBegin",
141 "A Multi-User Scheduler can only be aggregated to an HE AP");
163 (mpdu->GetHeader().IsQosData() && !mpdu->GetHeader().GetAddr1().IsGroup() &&
165 mpdu->GetHeader().GetQosTid()))))
184 "The Multi-user Scheduler returned DL_MU_TX with empty psduMap, do not transmit");
195 auto packet = Create<Packet>();
217 if (!mpdu->GetHeader().IsTrigger())
255 <<
") incompatible with Basic Trigger Frame");
259 <<
") incompatible with BSRP Trigger Frame");
261 auto txVector = trigger.GetHeTbTxVector(trigger.begin()->GetAid12());
278 if (mpdu->IsQueued())
310 NS_LOG_FUNCTION(
this << muRtsSize << muRtsTxVector << txDuration << response);
350 auto mpdu = Create<WifiMpdu>(payload, hdr);
353 mpdu->GetHeader().SetDuration(
396 if (mpdu->IsQueued())
404 const auto& hdr =
m_psduMap.cbegin()->second->GetHeader(0);
405 if (!hdr.GetAddr1().IsGroup())
410 if (!hdr.GetAddr1().IsGroup() &&
435 for (
const auto& [staId, psdu] :
m_psduMap)
446 auto it = std::find_if(
449 [&to](std::pair<uint16_t,
Ptr<WifiPsdu>> psdu) { return psdu.second->GetAddr1() == to; });
450 if (it != psduMap.end())
506 std::set<uint8_t> tids = psdu.second->
GetTids();
508 "Acknowledgment method incompatible with a Multi-TID A-MPDU");
509 uint8_t tid = *tids.begin();
526 mpdu = *psdu->
begin();
552 std::map<uint16_t, CtrlBAckRequestHeader> recipients;
563 staIt->second.blockAckTxVector.GetHeMuUserInfo(staId));
564 recipients.emplace(staId, staIt->second.barHeader);
637 auto psduMapIt = std::find_if(
m_psduMap.begin(),
640 return psdu.second->GetAddr1() == station.first;
645 std::vector<Ptr<WifiMpdu>> mpduList(psduMapIt->second->begin(),
646 psduMapIt->second->end());
647 NS_ASSERT(mpduList.size() == psduMapIt->second->GetNMpdus());
650 station.second.blockAckTxVector.SetLength(acknowledgment->
ulLength);
651 mpduList.push_back(
PrepareMuBar(station.second.blockAckTxVector,
652 {{psduMapIt->first, station.second.barHeader}}));
653 psduMapIt->second = Create<WifiPsdu>(std::move(mpduList));
656 station.second.blockAckTxVector.GetHeMuUserInfo(psduMapIt->first));
661 &acknowledgment->stationsReplyingWithBlockAck.begin()->second.blockAckTxVector;
671 mpdu = *m_psduMap.begin()->second->begin();
677 m_staExpectTbPpduFrom.clear();
681 m_staExpectTbPpduFrom.insert(station.first.first);
691 m_trigVector = GetTrigVector(m_muScheduler->GetUlMuInfo(m_linkId).trigger);
697 !m_txParams.m_txVector.IsUlMu() &&
IsTrigger(m_psduMap))
699 CtrlTriggerHeader& trigger = m_muScheduler->GetUlMuInfo(m_linkId).trigger;
704 m_staExpectTbPpduFrom.clear();
706 for (
const auto& userInfo : trigger)
708 auto staIt = m_apMac->GetStaList(m_linkId).find(userInfo.GetAid12());
709 NS_ASSERT(staIt != m_apMac->GetStaList(m_linkId).end());
710 m_staExpectTbPpduFrom.insert(staIt->second);
714 txVector = trigger.GetHeTbTxVector(trigger.begin()->GetAid12());
715 responseTxVector = &txVector;
716 m_trigVector = GetTrigVector(m_muScheduler->GetUlMuInfo(m_linkId).trigger);
721 else if (m_txParams.m_txVector.IsUlMu() &&
726 NS_ASSERT(m_staMac && m_staMac->IsAssociated());
727 txVector = GetWifiRemoteStationManager()->GetBlockAckTxVector(
728 m_psduMap.begin()->second->GetAddr1(),
729 m_txParams.m_txVector);
730 responseTxVector = &txVector;
735 else if (m_txParams.m_txVector.IsUlMu() &&
742 NS_ABORT_MSG(
"Unable to handle the selected acknowledgment method ("
743 << m_txParams.m_acknowledgment.get() <<
")");
748 for (
const auto& psdu : m_psduMap)
750 psduMap.emplace(psdu.first, psdu.second);
754 if (m_txParams.m_txVector.IsUlMu())
757 m_txParams.m_txVector,
758 m_phy->GetPhyBand());
763 m_phy->CalculateTxDuration(psduMap, m_txParams.m_txVector, m_phy->GetPhyBand());
766 Time durationId = GetPsduDurationId(txDuration, m_txParams);
767 for (
auto& psdu : m_psduMap)
769 psdu.second->SetDuration(durationId);
775 if (!m_txParams.m_txVector.IsUlMu())
782 Time timeout = txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
783 m_phy->CalculatePhyPreambleAndHeaderDuration(*responseTxVector);
784 m_channelAccessManager->NotifyAckTimeoutStartNow(
timeout);
791 m_txTimer.Set(timerType,
796 m_txParams.m_txVector);
800 m_txTimer.Set(timerType,
805 m_txParams.m_txVector);
808 m_txTimer.Set(timerType,
813 &m_staExpectTbPpduFrom,
814 m_staExpectTbPpduFrom.size());
818 m_txTimer.Set(timerType,
823 &m_staExpectTbPpduFrom,
824 m_staExpectTbPpduFrom.size());
827 m_txTimer.Set(timerType,
831 m_psduMap.begin()->second,
832 m_txParams.m_txVector);
841 ForwardPsduMapDown(psduMap, m_txParams.m_txVector);
848 auto hePhy = StaticCast<HePhy>(m_phy->GetPhyEntity(responseTxVector->GetModulationClass()));
849 hePhy->SetTrigVector(m_trigVector, m_txTimer.GetDelayLeft());
866 auto sigBMode = hePhy->GetSigBMode(txVector);
870 for (
const auto& psdu : psduMap)
872 NS_LOG_DEBUG(
"Transmitting: [STAID=" << psdu.first <<
", " << *psdu.second <<
"]");
875 for (
const auto& psdu : psduMap)
877 NotifyTxToEdca(psdu.second);
879 if (psduMap.size() > 1 || psduMap.begin()->second->IsAggregate() ||
880 psduMap.begin()->second->IsSingle())
885 m_phy->Send(psduMap, txVector);
889 HeFrameExchangeManager::PrepareMuBar(
const WifiTxVector& responseTxVector,
890 std::map<uint16_t, CtrlBAckRequestHeader> recipients)
const
897 SetTargetRssi(muBar);
903 for (
auto& userInfo : muBar)
905 auto recipientIt = recipients.find(userInfo.GetAid12());
906 NS_ASSERT(recipientIt != recipients.end());
909 userInfo.SetMuBarTriggerDepUserInfo(recipientIt->second);
921 rxAddress = Mac48Address::GetBroadcast();
926 rxAddress = m_apMac->GetStaList(m_linkId).at(recipients.begin()->first);
938 return Create<WifiMpdu>(bar, hdr);
942 HeFrameExchangeManager::CalculateProtectionTime(
WifiProtection* protection)
const
947 if (protection->
method == WifiProtection::MU_RTS_CTS)
955 GetCtsTxVectorAfterMuRts(muRtsCtsProtection->
muRts,
956 muRtsCtsProtection->
muRts.
begin()->GetAid12());
961 m_phy->CalculateTxDuration(muRtsSize,
963 m_phy->GetPhyBand()) +
964 m_phy->CalculateTxDuration(
GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()) +
965 2 * m_phy->GetSifs();
969 VhtFrameExchangeManager::CalculateProtectionTime(protection);
982 if (acknowledgment->
method == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
1000 m_phy->CalculateTxDuration(
GetAckSize(), info.ackTxVector, m_phy->GetPhyBand());
1007 duration += m_phy->GetSifs() + m_phy->CalculateTxDuration(
GetBlockAckSize(info.baType),
1008 info.blockAckTxVector,
1009 m_phy->GetPhyBand());
1014 const auto& info = stations.second;
1015 duration += m_phy->GetSifs() +
1017 info.blockAckReqTxVector,
1018 m_phy->GetPhyBand()) +
1021 info.blockAckTxVector,
1022 m_phy->GetPhyBand());
1030 else if (acknowledgment->
method == WifiAcknowledgment::DL_MU_TF_MU_BAR)
1039 const auto& info = stations.second;
1040 NS_ASSERT(info.blockAckTxVector.GetHeMuUserInfoMap().size() == 1);
1041 uint16_t staId = info.blockAckTxVector.GetHeMuUserInfoMap().begin()->first;
1043 info.blockAckTxVector,
1044 m_phy->GetPhyBand(),
1047 if (currBlockAckDuration > duration)
1049 duration = currBlockAckDuration;
1056 ->second.blockAckTxVector;
1057 std::tie(dlMuTfMuBarAcknowledgment->
ulLength, duration) =
1058 HePhy::ConvertHeTbPpduDurationToLSigLength(duration, txVector, m_phy->GetPhyBand());
1064 muBarSize = MpduAggregator::GetSizeIfAggregated(muBarSize, 0);
1068 m_phy->CalculateTxDuration(muBarSize,
1070 m_phy->GetPhyBand()) +
1071 m_phy->GetSifs() + duration;
1076 else if (acknowledgment->
method == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
1086 const auto& info = stations.second;
1087 NS_ASSERT(info.blockAckTxVector.GetHeMuUserInfoMap().size() == 1);
1088 uint16_t staId = info.blockAckTxVector.GetHeMuUserInfoMap().begin()->first;
1090 info.blockAckTxVector,
1091 m_phy->GetPhyBand(),
1094 if (currBlockAckDuration > duration)
1096 duration = currBlockAckDuration;
1104 std::tie(dlMuAggrTfAcknowledgment->
ulLength, duration) =
1105 HePhy::ConvertHeTbPpduDurationToLSigLength(duration, txVector, m_phy->GetPhyBand());
1111 else if (acknowledgment->
method == WifiAcknowledgment::UL_MU_MULTI_STA_BA)
1117 m_phy->GetPhyBand());
1123 else if (acknowledgment->
method == WifiAcknowledgment::ACK_AFTER_TB_PPDU)
1132 VhtFrameExchangeManager::CalculateAcknowledgmentTime(acknowledgment);
1137 HeFrameExchangeManager::GetCtsModeAfterMuRts()
const
1142 : OfdmPhy::GetOfdmRate6Mbps();
1147 uint16_t staId)
const
1152 NS_ASSERT_MSG(userInfoIt != trigger.
end(),
"User Info field for AID=" << staId <<
" not found");
1155 if (uint8_t ru = userInfoIt->GetMuRtsRuAllocation(); ru < 65)
1173 auto txVector = GetWifiRemoteStationManager()->GetCtsTxVector(m_bssid, GetCtsModeAfterMuRts());
1175 txVector.SetChannelWidth(bw);
1181 HeFrameExchangeManager::GetTxDuration(uint32_t ppduPayloadSize,
1187 return VhtFrameExchangeManager::GetTxDuration(ppduPayloadSize, receiver, txParams);
1194 txParams.
m_acknowledgment->method == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
1204 MpduAggregator::GetSizeIfAggregated(info->second.muBarSize, ppduPayloadSize);
1207 uint16_t staId = (txParams.
m_txVector.
IsDlMu() ? m_apMac->GetAssociationId(receiver, m_linkId)
1208 : m_staMac->GetAssociationId());
1209 Time psduDuration = m_phy->CalculateTxDuration(ppduPayloadSize,
1211 m_phy->GetPhyBand(),
1219 const std::set<Mac48Address>* staMissedTbPpduFrom,
1220 std::size_t nSolicitedStations)
1222 NS_LOG_FUNCTION(
this << psduMap << staMissedTbPpduFrom->size() << nSolicitedStations);
1228 NS_ASSERT(!staMissedTbPpduFrom->empty());
1231 if (staMissedTbPpduFrom->size() == nSolicitedStations)
1234 m_edca->UpdateFailedCw(m_linkId);
1236 TransmissionFailed();
1238 else if (!m_multiStaBaEvent.IsRunning())
1240 m_edca->ResetCw(m_linkId);
1241 TransmissionSucceeded();
1248 HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
1250 const std::set<Mac48Address>* staMissedBlockAckFrom,
1251 std::size_t nSolicitedStations)
1256 NS_ASSERT(m_txParams.m_acknowledgment &&
1257 (m_txParams.m_acknowledgment->method == WifiAcknowledgment::DL_MU_AGGREGATE_TF ||
1258 m_txParams.m_acknowledgment->method == WifiAcknowledgment::DL_MU_TF_MU_BAR));
1261 NS_ASSERT(!staMissedBlockAckFrom->empty());
1265 if (staMissedBlockAckFrom->size() == nSolicitedStations)
1269 GetWifiRemoteStationManager()->ReportDataFailed(*psduMap->begin()->second->begin());
1281 DequeueMpdu(m_triggerFrame);
1282 m_triggerFrame =
nullptr;
1285 for (
const auto& sta : *staMissedBlockAckFrom)
1294 MissedBlockAck(psdu, m_txParams.m_txVector, psduResetCw);
1295 resetCw = resetCw || psduResetCw;
1302 m_edca->ResetCw(m_linkId);
1306 m_edca->UpdateFailedCw(m_linkId);
1309 if (staMissedBlockAckFrom->size() == nSolicitedStations)
1312 TransmissionFailed();
1316 TransmissionSucceeded();
1329 GetWifiRemoteStationManager()->ReportDataFailed(*psdu->
begin());
1331 MissedBlockAck(psdu, m_txParams.m_txVector, resetCw);
1346 VhtFrameExchangeManager::NormalAckTimeout(mpdu, txVector);
1351 for (
auto& psdu : m_psduMap)
1355 if (mpdu->IsQueued())
1357 m_mac->GetTxopQueue(mpdu->GetQueueAc())->GetOriginal(mpdu)->GetHeader().SetRetry();
1358 mpdu->ResetInFlight(m_linkId);
1370 VhtFrameExchangeManager::BlockAckTimeout(psdu, txVector);
1375 for (
auto& psdu : m_psduMap)
1379 if (mpdu->IsQueued())
1381 mpdu->GetHeader().SetRetry();
1397 for (
const auto& userInfoField : trigger)
1400 userInfoField.GetAid12(),
1401 {userInfoField.GetRuAllocation(), userInfoField.GetUlMcs(), userInfoField.GetNss()});
1413 uint16_t staId = m_staMac->GetAssociationId();
1420 NS_ASSERT_MSG(heConfiguration,
"This STA has to be an HE station to send an HE TB PPDU");
1423 if (userInfoIt->IsUlTargetRssiMaxTxPower())
1425 NS_LOG_LOGIC(
"AP requested using the max transmit power (" << m_phy->GetTxPowerEnd()
1431 uint8_t powerLevel = GetWifiRemoteStationManager()->GetDefaultTxPowerLevel();
1449 auto optRssi = GetMostRecentRssi(triggerSender);
1453 static_cast<int8_t
>(
1455 double reqTxPowerDbm =
static_cast<double>(userInfoIt->GetUlTargetRssi() + pathLossDb);
1458 uint8_t numPowerLevels = m_phy->GetNTxPower();
1459 if (numPowerLevels > 1)
1461 double stepDbm = (m_phy->GetTxPowerEnd() - m_phy->GetTxPowerStart()) / (numPowerLevels - 1);
1462 powerLevel =
static_cast<uint8_t
>(
1463 ceil((reqTxPowerDbm - m_phy->GetTxPowerStart()) /
1465 if (powerLevel > numPowerLevels)
1467 powerLevel = numPowerLevels;
1470 if (reqTxPowerDbm > m_phy->GetPowerDbm(powerLevel))
1473 << reqTxPowerDbm <<
"dBm) cannot be satisfied (max: " << m_phy->GetTxPowerEnd()
1478 <<
"input {pathLoss=" << pathLossDb <<
"dB, reqTxPower=" << reqTxPowerDbm <<
"dBm}"
1479 <<
" output {powerLevel=" << +powerLevel <<
" -> "
1480 << m_phy->GetPowerDbm(powerLevel) <<
"dBm}"
1481 <<
" PHY power capa {min=" << m_phy->GetTxPowerStart() <<
"dBm, max="
1482 << m_phy->GetTxPowerEnd() <<
"dBm, levels:" << +numPowerLevels <<
"}");
1487 std::optional<double>
1490 return GetWifiRemoteStationManager()->GetMostRecentRssi(
address);
1500 m_phy->GetPowerDbm(GetWifiRemoteStationManager()->GetDefaultTxPowerLevel())));
1501 for (
auto& userInfo : trigger)
1503 const auto staList = m_apMac->GetStaList(m_linkId);
1504 auto itAidAddr = staList.find(userInfo.GetAid12());
1506 auto optRssi = GetMostRecentRssi(itAidAddr->second);
1508 int8_t rssi =
static_cast<int8_t
>(*optRssi);
1509 rssi = (rssi >= -20)
1511 : ((rssi <= -110) ? -110 : rssi);
1512 userInfo.SetUlTargetRssi(rssi);
1521 auto txVectorCopy = txVector;
1540 if (m_staMac !=
nullptr && m_staMac->IsAssociated() &&
1551 psdu = Create<const WifiPsdu>(Create<Packet>(), rts);
1555 GetWifiRemoteStationManager()->GetCtsTxVector(m_bssid, GetCtsModeAfterMuRts());
1558 VhtFrameExchangeManager::PostProcessFrame(psdu, txVectorCopy);
1568 NS_ASSERT(m_staMac !=
nullptr && m_staMac->IsAssociated());
1569 WifiTxVector ctsTxVector = GetCtsTxVectorAfterMuRts(trigger, m_staMac->GetAssociationId());
1572 DoSendCtsAfterRts(muRtsHdr, ctsTxVector, muRtsSnr);
1582 txParams.
m_acknowledgment->method == WifiAcknowledgment::UL_MU_MULTI_STA_BA);
1595 receiver = staInfo.first.first;
1596 uint8_t tid = staInfo.first.second;
1597 std::size_t index = staInfo.second;
1599 blockAck.
SetAid11(m_apMac->GetAssociationId(receiver, m_linkId), index);
1605 NS_LOG_DEBUG(
"Multi-STA Block Ack: Sending All-ack to=" << receiver);
1613 NS_LOG_DEBUG(
"Multi-STA Block Ack: Sending Ack to=" << receiver);
1621 auto agreement = m_mac->GetBaAgreementEstablishedAsRecipient(receiver, tid);
1623 agreement->get().FillBlockAckBitmap(&blockAck, index);
1624 NS_LOG_DEBUG(
"Multi-STA Block Ack: Sending Block Ack with seq="
1626 <<
" tid=" << +tid);
1634 : Mac48Address::GetBroadcast());
1646 m_phy->GetPhyBand());
1658 if (m_edca->GetTxopLimit(m_linkId).IsZero())
1675 m_edca->ResetCw(m_linkId);
1677 Simulator::Schedule(txDuration, &HeFrameExchangeManager::TransmissionSucceeded,
this);
1686 NS_ASSERT(m_staMac && m_staMac->IsAssociated());
1688 NS_LOG_DEBUG(
"Received a Trigger Frame (basic variant) soliciting a transmission");
1690 if (!UlMuCsMediumIdle(trigger))
1701 std::vector<uint8_t> tids;
1702 uint16_t staId = m_staMac->GetAssociationId();
1705 for (uint8_t i = 0; i < 4; i++)
1708 tids.push_back(acIt->second.GetHighTid());
1709 tids.push_back(acIt->second.GetLowTid());
1721 Time ppduDuration = HePhy::ConvertLSigLengthToHeTbPpduDuration(trigger.
GetUlLength(),
1723 m_phy->GetPhyBand());
1725 for (
const auto& tid : tids)
1729 if (!m_mac->GetBaAgreementEstablishedAsOriginator(hdr.
GetAddr2(), tid))
1740 mpdu && TryAddMpdu(mpdu, txParams, ppduDuration))
1743 psdu = Create<WifiPsdu>(mpdu,
true);
1749 GetWifiRemoteStationManager()->GetMldAddress(hdr.
GetAddr2()).value_or(hdr.
GetAddr2());
1750 if (
auto mpdu = edca->
PeekNextMpdu(m_linkId, tid, receiver))
1752 mpdu = CreateAliasIfNeeded(mpdu);
1753 if (
auto item = edca->
GetNextMpdu(m_linkId, mpdu, txParams, ppduDuration,
false))
1756 std::vector<Ptr<WifiMpdu>> mpduList =
1757 m_mpduAggregator->GetNextAmpdu(item, txParams, ppduDuration);
1758 psdu = (mpduList.size() > 1 ? Create<WifiPsdu>(std::move(mpduList))
1759 : Create<WifiPsdu>(item,
true));
1768 SendPsduMapWithProtection(
WifiPsduMap{{staId, psdu}}, txParams);
1773 SendQosNullFramesInTbPpdu(trigger, hdr);
1783 NS_ASSERT(m_staMac && m_staMac->IsAssociated());
1787 if (!UlMuCsMediumIdle(trigger))
1810 Time ppduDuration = HePhy::ConvertLSigLengthToHeTbPpduDuration(trigger.
GetUlLength(),
1812 m_phy->GetPhyBand());
1816 std::vector<Ptr<WifiMpdu>> mpduList;
1821 IsWithinSizeAndTimeLimits(
1822 txParams.
GetSizeIfAddMpdu(mpdu = Create<WifiMpdu>(Create<Packet>(), header)),
1827 if (!m_mac->GetBaAgreementEstablishedAsOriginator(hdr.
GetAddr2(), tid))
1829 NS_LOG_DEBUG(
"Skipping tid=" << +tid <<
" because no agreement established");
1834 NS_LOG_DEBUG(
"Aggregating a QoS Null frame with tid=" << +tid);
1842 UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
1843 mpduList.push_back(mpdu);
1847 if (mpduList.empty())
1849 NS_LOG_DEBUG(
"Not enough time to send a QoS Null frame");
1853 Ptr<WifiPsdu> psdu = (mpduList.size() > 1 ? Create<WifiPsdu>(std::move(mpduList))
1854 : Create<WifiPsdu>(mpduList.front(),
true));
1855 uint16_t staId = m_staMac->GetAssociationId();
1856 SendPsduMapWithProtection(
WifiPsduMap{{staId, psdu}}, txParams);
1867 auto agreement = m_mac->GetBaAgreementEstablishedAsRecipient(m_bssid, tid);
1871 NS_LOG_DEBUG(
"There's not a valid agreement for this BlockAckReq");
1875 if (!UlMuCsMediumIdle(trigger))
1881 auto txVector = GetHeTbTxVector(trigger, m_bssid);
1882 SendBlockAck(*agreement, durationId, txVector, snr);
1901 if (ra == m_bssid || ta == m_bssid || bssid == m_bssid)
1909 if (psdu->
GetHeader(0).
IsCtl() && ta == empty && ra == m_txopHolder)
1923 if (bssid != empty && bssid != m_bssid)
1931 if (bssid == empty && ta != empty && ra != empty && ta != m_bssid && ra != m_bssid)
1944 const auto bssColor = m_mac->GetHeConfiguration()->GetBssColor();
1945 if (bssColor != 0 && bssColor == txVector.
GetBssColor())
1974 if (!IsIntraBssPpdu(psdu, txVector))
1976 NS_LOG_DEBUG(
"PPDU not classified as intra-BSS, update the basic NAV");
1977 VhtFrameExchangeManager::UpdateNav(psdu, txVector);
1981 NS_LOG_DEBUG(
"PPDU classified as intra-BSS, update the intra-BSS NAV");
1988 if (intraBssNavEnd > m_intraBssNavEnd)
1990 m_intraBssNavEnd = intraBssNavEnd;
1991 NS_LOG_DEBUG(
"Updated intra-BSS NAV=" << m_intraBssNavEnd);
2005 GetWifiRemoteStationManager()->GetCtsTxVector(psdu->
GetAddr2(), txVector.
GetMode());
2006 auto navResetDelay =
2007 2 * m_phy->GetSifs() +
2008 WifiPhy::CalculateTxDuration(
GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()) +
2009 m_phy->CalculatePhyPreambleAndHeaderDuration(ctsTxVector) + 2 * m_phy->GetSlot();
2010 m_intraBssNavResetEvent =
2011 Simulator::Schedule(navResetDelay,
2012 &HeFrameExchangeManager::IntraBssNavResetTimeout,
2016 NS_LOG_DEBUG(
"Current intra-BSS NAV=" << m_intraBssNavEnd);
2018 m_channelAccessManager->NotifyNavStartNow(duration);
2022 HeFrameExchangeManager::ClearTxopHolderIfNeeded()
2027 m_txopHolder.reset();
2032 HeFrameExchangeManager::NavResetTimeout()
2038 Time intraBssNav = Simulator::GetDelayLeft(m_intraBssNavResetEvent);
2039 m_channelAccessManager->NotifyNavResetNow(intraBssNav);
2043 HeFrameExchangeManager::IntraBssNavResetTimeout()
2047 ClearTxopHolderIfNeeded();
2049 Time basicNav = Simulator::GetDelayLeft(m_navResetEvent);
2050 m_channelAccessManager->NotifyNavResetNow(basicNav);
2060 m_txopHolder = m_bssid;
2062 else if (!txVector.
IsUlMu())
2064 VhtFrameExchangeManager::SetTxopHolder(psdu, txVector);
2069 HeFrameExchangeManager::VirtualCsMediumIdle()
const
2097 NS_ASSERT_MSG(m_staMac,
"UL MU CS is only performed by non-AP STAs");
2100 "No User Info field for STA (" << m_self
2101 <<
") AID=" << m_staMac->GetAssociationId());
2103 std::set<uint8_t> indices;
2107 auto ctsTxVector = GetCtsTxVectorAfterMuRts(trigger, m_staMac->GetAssociationId());
2108 auto bw = ctsTxVector.GetChannelWidth();
2109 indices = m_phy->GetOperatingChannel().GetAll20MHzChannelIndicesInPrimary(bw);
2114 m_phy->GetOperatingChannel().Get20MHzIndicesCoveringRu(userInfoIt->GetRuAllocation(),
2117 return !m_channelAccessManager->GetPer20MHzBusy(indices);
2127 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
2131 if (txVector.
IsUlMu() && m_txTimer.IsRunning() &&
2132 m_txTimer.GetReason() == WifiTxTimer::WAIT_TB_PPDU_AFTER_BASIC_TF)
2135 NS_ASSERT(m_txParams.m_acknowledgment &&
2136 m_txParams.m_acknowledgment->method == WifiAcknowledgment::UL_MU_MULTI_STA_BA);
2141 if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
2143 NS_LOG_WARN(
"Received a TB PPDU from an unexpected station: " << sender);
2149 NS_LOG_DEBUG(
"Received a BlockAckReq in a TB PPDU from " << sender);
2152 mpdu->GetPacket()->PeekHeader(blockAckReq);
2155 GetBaManager(tid)->NotifyGotBlockAckRequest(
2156 m_mac->GetMldAddress(sender).value_or(sender),
2163 m_mac->GetBaTypeAsRecipient(sender, tid).m_bitmapLen.at(0));
2165 m_muSnrTag.Set(staId, rxSignalInfo.
snr);
2169 NS_LOG_DEBUG(
"Received an S-MPDU in a TB PPDU from " << sender <<
" (" << *mpdu <<
")");
2172 GetBaManager(tid)->NotifyGotMpdu(mpdu);
2178 m_muSnrTag.Set(staId, rxSignalInfo.
snr);
2187 VhtFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
2194 m_multiStaBaEvent = Simulator::Schedule(m_phy->GetSifs(),
2195 &HeFrameExchangeManager::SendMultiStaBlockAck,
2197 std::cref(m_txParams),
2198 mpdu->GetHeader().GetDuration());
2202 m_staExpectTbPpduFrom.erase(sender);
2204 if (m_staExpectTbPpduFrom.empty())
2208 m_channelAccessManager->NotifyAckTimeoutResetNow();
2210 if (!m_multiStaBaEvent.IsRunning())
2215 m_edca->ResetCw(m_linkId);
2216 TransmissionSucceeded();
2224 if (txVector.
IsUlMu() && m_txTimer.IsRunning() &&
2225 m_txTimer.GetReason() == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF &&
2228 const auto& sender = hdr.
GetAddr2();
2230 if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
2232 NS_LOG_WARN(
"Received a TB PPDU from an unexpected station: " << sender);
2237 NS_LOG_WARN(
"No QoS Null frame in the received MPDU");
2241 NS_LOG_DEBUG(
"Received a QoS Null frame in a TB PPDU from " << sender);
2244 m_staExpectTbPpduFrom.erase(sender);
2246 if (m_staExpectTbPpduFrom.empty())
2250 m_channelAccessManager->NotifyAckTimeoutResetNow();
2254 m_edca->ResetCw(m_linkId);
2255 TransmissionSucceeded();
2264 if (hdr.
IsCts() && m_txTimer.IsRunning() &&
2265 m_txTimer.GetReason() == WifiTxTimer::WAIT_CTS && m_psduMap.size() == 1)
2270 Mac48Address sender = m_psduMap.begin()->second->GetAddr1();
2274 mpdu->GetPacket()->PeekPacketTag(tag);
2275 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
2276 GetWifiRemoteStationManager()->ReportRtsOk(m_psduMap.begin()->second->GetHeader(0),
2282 m_channelAccessManager->NotifyCtsTimeoutResetNow();
2283 Simulator::Schedule(m_phy->GetSifs(), &HeFrameExchangeManager::SendPsduMap,
this);
2285 else if (hdr.
IsCts() && !m_psduMap.empty() && m_txTimer.IsRunning() &&
2286 m_txTimer.GetReason() == WifiTxTimer::WAIT_CTS_AFTER_MU_RTS)
2291 NS_LOG_DEBUG(
"Received a CTS frame in response to an MU-RTS");
2294 m_channelAccessManager->NotifyCtsTimeoutResetNow();
2295 Simulator::Schedule(m_phy->GetSifs(), &HeFrameExchangeManager::SendPsduMap,
this);
2297 else if (hdr.
IsAck() && m_txTimer.IsRunning() &&
2298 m_txTimer.GetReason() == WifiTxTimer::WAIT_NORMAL_ACK_AFTER_DL_MU_PPDU)
2302 NS_ASSERT(m_txParams.m_acknowledgment->method ==
2303 WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE);
2309 uint16_t staId = m_apMac->GetAssociationId(
2312 auto it = m_psduMap.find(staId);
2317 mpdu->GetPacket()->PeekPacketTag(tag);
2318 ReceivedNormalAck(*it->second->begin(),
2319 m_txParams.m_txVector,
2332 m_txTimer.GetReason() == WifiTxTimer::WAIT_BLOCK_ACKS_IN_TB_PPDU)
2335 NS_LOG_DEBUG(
"Received BlockAck in TB PPDU from=" << sender);
2338 mpdu->GetPacket()->PeekPacketTag(tag);
2342 mpdu->GetPacket()->PeekHeader(blockAck);
2344 std::pair<uint16_t, uint16_t> ret =
2345 GetBaManager(tid)->NotifyGotBlockAck(m_linkId,
2347 m_mac->GetMldAddress(sender).value_or(sender),
2349 GetWifiRemoteStationManager()->ReportAmpduTxStatus(sender,
2354 m_txParams.m_txVector);
2357 if (m_staExpectTbPpduFrom.erase(sender) == 0)
2359 NS_LOG_WARN(
"Received a BlockAck from an unexpected stations: " << sender);
2363 if (m_staExpectTbPpduFrom.empty())
2367 m_channelAccessManager->NotifyAckTimeoutResetNow();
2371 DequeueMpdu(m_triggerFrame);
2372 m_triggerFrame =
nullptr;
2375 m_edca->ResetCw(m_linkId);
2377 TransmissionSucceeded();
2380 else if (hdr.
IsBlockAck() && m_txTimer.IsRunning() &&
2381 m_txTimer.GetReason() == WifiTxTimer::WAIT_BLOCK_ACK_AFTER_TB_PPDU)
2384 mpdu->GetPacket()->PeekHeader(blockAck);
2387 "A Multi-STA BlockAck is expected after a TB PPDU");
2390 NS_ASSERT(m_staMac && m_staMac->IsAssociated());
2393 NS_LOG_DEBUG(
"The sender is not the AP we are associated with");
2397 uint16_t staId = m_staMac->GetAssociationId();
2400 if (indices.empty())
2402 NS_LOG_DEBUG(
"No Per AID TID Info subfield intended for me");
2407 mpdu->GetPacket()->PeekPacketTag(tag);
2410 for (
const auto& index : indices)
2417 NS_ABORT_IF(m_psduMap.empty() || m_psduMap.begin()->first != staId);
2418 GetBaManager(tid)->NotifyGotAck(m_linkId, *m_psduMap.at(staId)->begin());
2427 NS_ABORT_IF(m_psduMap.empty() || m_psduMap.begin()->first != staId);
2428 std::set<uint8_t> tids = m_psduMap.at(staId)->GetTids();
2429 NS_ABORT_MSG_IF(tids.size() > 1,
"Multi-TID A-MPDUs not supported yet");
2430 tid = *tids.begin();
2433 std::pair<uint16_t, uint16_t> ret = GetBaManager(tid)->NotifyGotBlockAck(
2439 GetWifiRemoteStationManager()->ReportAmpduTxStatus(hdr.
GetAddr2(),
2444 m_txParams.m_txVector);
2447 if (m_psduMap.at(staId)->GetHeader(0).IsQosData() &&
2449 || std::any_of(blockAck.
GetBitmap(index).begin(),
2451 [](uint8_t b) { return b != 0; })))
2453 NS_ASSERT(m_psduMap.at(staId)->GetHeader(0).HasData());
2454 NS_ASSERT(m_psduMap.at(staId)->GetHeader(0).GetQosTid() == tid);
2459 m_mac->GetQosTxop(tid)->StartMuEdcaTimerNow(m_linkId);
2465 m_channelAccessManager->NotifyAckTimeoutResetNow();
2467 for (
const auto& [staId, psdu] : m_psduMap)
2469 if (psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsBlockAckReq())
2476 else if (hdr.
IsBlockAck() && m_txTimer.IsRunning() &&
2477 m_txTimer.GetReason() == WifiTxTimer::WAIT_BLOCK_ACK)
2483 VhtFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
2496 m_triggerFrameInAmpdu =
true;
2501 mpdu->GetPacket()->PeekHeader(trigger);
2512 uint16_t staId = m_staMac->GetAssociationId();
2517 NS_LOG_DEBUG(
"Received MU-RTS Trigger Frame from=" << sender);
2518 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
2527 if (UlMuCsMediumIdle(trigger))
2530 Simulator::Schedule(m_phy->GetSifs(),
2531 &HeFrameExchangeManager::SendCtsAfterMuRts,
2545 NS_LOG_DEBUG(
"Received MU-BAR Trigger Frame from=" << sender);
2546 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
2554 GetBaManager(tid)->NotifyGotBlockAckRequest(
2555 m_mac->GetMldAddress(sender).value_or(sender),
2559 Simulator::Schedule(m_phy->GetSifs(),
2560 &HeFrameExchangeManager::ReceiveMuBarTrigger,
2569 Simulator::Schedule(m_phy->GetSifs(),
2570 &HeFrameExchangeManager::ReceiveBasicTrigger,
2575 else if (trigger.
IsBsrp())
2577 Simulator::Schedule(m_phy->GetSifs(),
2578 &HeFrameExchangeManager::SendQosNullFramesInTbPpdu,
2587 VhtFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
2595 VhtFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
2603 const std::vector<bool>& perMpduStatus)
2605 std::set<uint8_t> tids = psdu->
GetTids();
2607 if (txVector.
IsUlMu() && m_txTimer.IsRunning() &&
2608 m_txTimer.GetReason() == WifiTxTimer::WAIT_TB_PPDU_AFTER_BASIC_TF)
2611 NS_ASSERT(m_txParams.m_acknowledgment &&
2612 m_txParams.m_acknowledgment->method == WifiAcknowledgment::UL_MU_MULTI_STA_BA);
2617 if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
2619 NS_LOG_WARN(
"Received a TB PPDU from an unexpected station: " << sender);
2623 NS_LOG_DEBUG(
"Received an A-MPDU in a TB PPDU from " << sender <<
" (" << *psdu <<
")");
2625 if (std::any_of(tids.begin(), tids.end(), [&psdu](uint8_t tid) {
2626 return psdu->GetAckPolicyForTid(tid) == WifiMacHeader::NORMAL_ACK;
2629 if (std::all_of(perMpduStatus.cbegin(), perMpduStatus.cend(), [](
bool v) { return v; }))
2640 for (
const auto& tid : tids)
2645 m_mac->GetBaTypeAsRecipient(sender, tid).m_bitmapLen.at(0));
2649 m_muSnrTag.Set(staId, rxSignalInfo.
snr);
2655 m_multiStaBaEvent = Simulator::Schedule(m_phy->GetSifs(),
2656 &HeFrameExchangeManager::SendMultiStaBlockAck,
2658 std::cref(m_txParams),
2663 m_staExpectTbPpduFrom.erase(sender);
2665 if (m_staExpectTbPpduFrom.empty())
2669 m_channelAccessManager->NotifyAckTimeoutResetNow();
2671 if (!m_multiStaBaEvent.IsRunning())
2676 m_edca->ResetCw(m_linkId);
2677 TransmissionSucceeded();
2685 if (txVector.
IsUlMu() && m_txTimer.IsRunning() &&
2686 m_txTimer.GetReason() == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF)
2690 if (m_staExpectTbPpduFrom.find(sender) == m_staExpectTbPpduFrom.end())
2692 NS_LOG_WARN(
"Received a TB PPDU from an unexpected station: " << sender);
2696 return mpdu->GetHeader().IsQosData() && !mpdu->GetHeader().HasData();
2699 NS_LOG_WARN(
"No QoS Null frame in the received PSDU");
2703 NS_LOG_DEBUG(
"Received QoS Null frames in a TB PPDU from " << sender);
2706 m_staExpectTbPpduFrom.erase(sender);
2708 if (m_staExpectTbPpduFrom.empty())
2712 m_channelAccessManager->NotifyAckTimeoutResetNow();
2716 m_edca->ResetCw(m_linkId);
2717 TransmissionSucceeded();
2724 if (m_triggerFrameInAmpdu)
2727 auto psduIt = psdu->
begin();
2728 while (psduIt != psdu->
end())
2730 if ((*psduIt)->GetHeader().IsTrigger())
2732 ReceiveMpdu(*psduIt, rxSignalInfo, txVector,
false);
2737 m_triggerFrameInAmpdu =
false;
2742 VhtFrameExchangeManager::EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
uint16_t GetAssociationId(Mac48Address addr, uint8_t linkId) const
void NotifyAckTimeoutStartNow(Time duration)
Notify that ack timer has started for the given duration.
void NotifyCtsTimeoutStartNow(Time duration)
Notify that CTS timer has started for the given duration.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
void DoCtsTimeout(Ptr< WifiPsdu > psdu)
Take required actions when the CTS timer fired after sending an RTS to protect the given PSDU expires...
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
virtual void Reset()
Reset this frame exchange manager.
Mac48Address m_self
the MAC address of this device
uint16_t m_allowedWidth
the allowed width in MHz for the current transmission
WifiTxTimer m_txTimer
the timer set upon frame transmission
void SendRts(const WifiTxParameters &txParams)
Send RTS to begin RTS-CTS-Data-Ack transaction.
Ptr< WifiPhy > m_phy
the PHY layer on this station
virtual void SetWifiPhy(const Ptr< WifiPhy > phy)
Set the PHY layer to use.
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
virtual Time GetMuRtsDurationId(uint32_t muRtsSize, const WifiTxVector &muRtsTxVector, Time txDuration, Time response) const
Compute how to set the Duration/ID field of an MU-RTS Trigger Frame to send to protect a frame transm...
Ptr< ApWifiMac > m_apMac
MAC pointer (null if not an AP)
void SetWifiPhy(const Ptr< WifiPhy > phy) override
Set the PHY layer to use.
void DoDispose() override
Destructor implementation.
void Reset() override
Reset this frame exchange manager.
WifiMode GetCtsModeAfterMuRts() const
Ptr< WifiMpdu > PrepareMuBar(const WifiTxVector &responseTxVector, std::map< uint16_t, CtrlBAckRequestHeader > recipients) const
Build a MU-BAR Trigger Frame starting from the TXVECTOR used to respond to the MU-BAR (in case of mul...
void SendMuRts(const WifiTxParameters &txParams)
Send an MU-RTS to begin an MU-RTS/CTS frame exchange protecting an MU PPDU.
WifiTxParameters m_txParams
the TX parameters for the current PPDU
void BlockAckTimeout(Ptr< WifiPsdu > psdu, const WifiTxVector &txVector) override
Called when the BlockAck timeout expires.
uint16_t GetSupportedBaBufferSize() const override
Get the maximum supported buffer size for a Block Ack agreement.
void CalculateAcknowledgmentTime(WifiAcknowledgment *acknowledgment) const override
Calculate the time required to acknowledge a frame according to the given acknowledgment method.
Ptr< WifiMpdu > m_triggerFrame
Trigger Frame being sent.
void SetMultiUserScheduler(const Ptr< MultiUserScheduler > muScheduler)
Set the Multi-user Scheduler associated with this Frame Exchange Manager.
virtual void TbPpduTimeout(WifiPsduMap *psduMap, const std::set< Mac48Address > *staMissedTbPpduFrom, std::size_t nSolicitedStations)
Take the necessary actions after that some TB PPDUs are missing in response to Trigger Frame.
WifiTxVector GetCtsTxVectorAfterMuRts(const CtrlTriggerHeader &trigger, uint16_t staId) const
Get the TXVECTOR that the station having the given station ID has to use to send a CTS frame after re...
void SetWifiMac(const Ptr< WifiMac > mac) override
Set the MAC layer to use.
Ptr< MultiUserScheduler > m_muScheduler
Multi-user Scheduler (HE APs only)
virtual void CtsAfterMuRtsTimeout(Ptr< WifiMpdu > muRts, const WifiTxVector &txVector)
Called when no CTS frame is received after an MU-RTS.
WifiTxVector m_trigVector
the TRIGVECTOR
static Ptr< WifiPsdu > GetPsduTo(Mac48Address to, const WifiPsduMap &psduMap)
Get the PSDU in the given PSDU map that is addressed to the given MAC address, if any,...
Ptr< StaWifiMac > m_staMac
MAC pointer (null if not a STA)
void CtsTimeout(Ptr< WifiMpdu > rts, const WifiTxVector &txVector) override
Called when the CTS timeout expires.
EventId m_intraBssNavResetEvent
the event to reset the intra-BSS NAV after an RTS
bool StartFrameExchange(Ptr< QosTxop > edca, Time availableTime, bool initialFrame) override
Start a frame exchange (including protection frames and acknowledgment frames as needed) that fits wi...
std::set< Mac48Address > m_staExpectTbPpduFrom
set of stations expected to send a TB PPDU
void NormalAckTimeout(Ptr< WifiMpdu > mpdu, const WifiTxVector &txVector) override
Called when the Ack timeout expires.
virtual void BlockAckAfterTbPpduTimeout(Ptr< WifiPsdu > psdu, const WifiTxVector &txVector)
Take the necessary actions after that a Block Ack is missing after a TB PPDU solicited through a Trig...
void SendPsduMap()
Send the current PSDU map as a DL MU PPDU.
WifiPsduMap m_psduMap
the A-MPDU being transmitted
static TypeId GetTypeId()
Get the type ID.
Time m_intraBssNavEnd
intra-BSS NAV expiration time
bool SendMpduFromBaManager(Ptr< WifiMpdu > mpdu, Time availableTime, bool initialFrame) override
If the given MPDU contains a BlockAckReq frame (the duration of which plus the response fits within t...
virtual void BlockAcksInTbPpduTimeout(WifiPsduMap *psduMap, const std::set< Mac48Address > *staMissedBlockAckFrom, std::size_t nSolicitedStations)
Take the necessary actions after that some BlockAck frames are missing in response to a DL MU PPDU.
EventId m_multiStaBaEvent
Sending a Multi-STA BlockAck event.
void SendPsduMapWithProtection(WifiPsduMap psduMap, WifiTxParameters &txParams)
Send a map of PSDUs as a DL MU PPDU.
~HeFrameExchangeManager() override
static Time ConvertLSigLengthToHeTbPpduDuration(uint16_t length, const WifiTxVector &txVector, WifiPhyBand band)
void CtsTimeout(Ptr< WifiMpdu > rts, const WifiTxVector &txVector) override
Called when the CTS timeout expires.
Ptr< WifiMpdu > GetBar(AcIndex ac, std::optional< uint8_t > optTid=std::nullopt, std::optional< Mac48Address > optAddress=std::nullopt)
Get the next BlockAckRequest or MU-BAR Trigger Frame to send, if any.
virtual Time GetPsduDurationId(Time txDuration, const WifiTxParameters &txParams) const
Compute how to set the Duration/ID field of PSDUs that do not include fragments.
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
virtual bool SendMpduFromBaManager(Ptr< WifiMpdu > mpdu, Time availableTime, bool initialFrame)
If the given MPDU contains a BlockAckReq frame (the duration of which plus the response fits within t...
void SetWifiMac(const Ptr< WifiMac > mac) override
Set the MAC layer to use.
void ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector) override
Forward an MPDU down to the PHY layer.
void DoDispose() override
Destructor implementation.
bool StartFrameExchange(Ptr< QosTxop > edca, Time availableTime, bool initialFrame) override
Start a frame exchange (including protection frames and acknowledgment frames as needed) that fits wi...
void NotifyPacketDiscarded(Ptr< const WifiMpdu > mpdu) override
Pass the given MPDU, discarded because of the max retry limit was reached, to the MPDU dropped callba...
virtual void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector)
Forward a PSDU down to the PHY layer.
void DequeuePsdu(Ptr< const WifiPsdu > psdu)
Dequeue the MPDUs of the given PSDU from the queue in which they are stored.
void ReleaseSequenceNumbers(Ptr< const WifiPsdu > psdu) const override
Make the sequence numbers of MPDUs included in the given PSDU available again if the MPDUs have never...
static Mac48Address GetBroadcast()
A tag to be attached to a response to a multi-user UL frame, that carries the SNR values with which t...
double Get(uint16_t staId) const
Return the SNR value for the given sender.
TxFormat
Enumeration of the possible transmission formats.
void AddHeader(const Header &header)
Add header to this packet.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
void TransmissionFailed() override
Take necessary actions upon a transmission failure.
Ptr< QosTxop > m_edca
the EDCAF that gained channel access
Time GetRtsDurationId(const WifiTxVector &rtsTxVector, Time txDuration, Time response) const override
Compute how to set the Duration/ID field of an RTS frame to send to protect a frame transmitted with ...
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMpdu > mpdu=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
AcIndex GetAccessCategory() const
Get the access category of this object.
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
Ptr< WifiMpdu > GetNextMpdu(uint8_t linkId, Ptr< WifiMpdu > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame)
Prepare the frame to transmit on the given link starting from the MPDU that has been previously peeke...
Ptr< WifiMpdu > PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
Introspection did not find any typical Config paths.
double Get() const
Return the SNR value.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
bool IsZero() const
Exactly equivalent to t == 0.
Time GetTxopLimit() const
Return the TXOP limit.
void UpdateFailedCw(uint8_t linkId)
Update the value of the CW variable for the given link to take into account a transmission failure.
void ResetCw(uint8_t linkId)
Update the value of the CW variable for the given link to take into account a transmission success or...
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
VhtFrameExchangeManager handles the frame exchange sequences for VHT stations.
Ptr< WifiPsdu > GetWifiPsdu(Ptr< WifiMpdu > mpdu, const WifiTxVector &txVector) const override
Get a PSDU containing the given MPDU.
static void SetQosAckPolicy(Ptr< WifiMpdu > item, const WifiAcknowledgment *acknowledgment)
Set the QoS Ack policy for the given MPDU, which must be a QoS data frame.
Ptr< HeConfiguration > GetHeConfiguration() const
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
represent a single transmission mode
Time GetSlot() const
Return the slot duration for this PHY.
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
std::set< uint8_t > GetTids() const
Get the set of TIDs of the QoS Data frames included in the PSDU.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Time GetDuration() const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
std::vector< Ptr< WifiMpdu > >::const_iterator end() const
Return a const iterator to past-the-last MPDU.
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Ptr< const Packet > GetPayload(std::size_t i) const
Get the payload of the i-th MPDU.
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
void ReportFinalRtsFailed(const WifiMacHeader &header)
Should be invoked after calling ReportRtsFailed if NeedRetransmission returns false.
void ReportRtsFailed(const WifiMacHeader &header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
uint32_t GetSizeIfAddMpdu(Ptr< const WifiMpdu > mpdu) const
Get the size in bytes of the frame in case the given MPDU is added.
std::unique_ptr< WifiProtection > m_protection
protection method
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
Time m_txDuration
TX duration of the frame.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void AddMpdu(Ptr< const WifiMpdu > mpdu)
Record that an MPDU is being added to the current frame.
void Clear()
Reset the TX parameters.
bool IsRunning() const
Return true if the timer is running.
void Set(Reason reason, const Time &delay, MEM mem_ptr, OBJ obj, Args... args)
This method is called when a frame soliciting a response is transmitted.
Reason
The reason why the timer was started.
@ WAIT_BLOCK_ACK_AFTER_TB_PPDU
@ WAIT_NORMAL_ACK_AFTER_DL_MU_PPDU
@ WAIT_QOS_NULL_AFTER_BSRP_TF
@ WAIT_TB_PPDU_AFTER_BASIC_TF
@ WAIT_BLOCK_ACKS_IN_TB_PPDU
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
uint8_t GetBssColor() const
Get the BSS color.
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetTriggerResponding(bool triggerResponding)
Set the Trigger Responding parameter to the given value.
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
void SetBssColor(uint8_t color)
Set the BSS color.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Time Seconds(double value)
Construct a Time in the indicated unit.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
Declaration of ns3::HePhy class and ns3::HeSigAParameters struct.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
bool IsTrigger(const WifiPsduMap &psduMap)
uint32_t GetBlockAckRequestSize(BlockAckReqType type)
Return the total BlockAckRequest size (including FCS trailer).
uint32_t GetMuBarSize(std::list< BlockAckReqType > types)
Return the total MU-BAR size (including FCS trailer).
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
uint32_t GetAckSize()
Return the total Ack size (including FCS trailer).
uint32_t GetCtsSize()
Return the total CTS size (including FCS trailer).
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
U * PeekPointer(const Ptr< U > &p)
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.
RxSignalInfo structure containing info on the received signal.
double snr
SNR in linear scale.
WifiAcknowledgment is an abstract base struct.
Time acknowledgmentTime
time required by the acknowledgment method
const Method method
acknowledgment method
WifiDlMuAggregateTf specifies that a DL MU PPDU made of PSDUs including each a MU-BAR Trigger Frame i...
uint16_t ulLength
the UL Length field of the MU-BAR Trigger Frames
std::map< Mac48Address, BlockAckInfo > stationsReplyingWithBlockAck
Set of stations replying with a BlockAck frame.
WifiDlMuBarBaSequence specifies that a DL MU PPDU is acknowledged through a sequence of BlockAckReq a...
std::map< Mac48Address, BlockAckReqInfo > stationsSendBlockAckReqTo
Set of stations receiving a BlockAckReq frame and replying with a BlockAck frame.
std::map< Mac48Address, BlockAckInfo > stationsReplyingWithBlockAck
Set of stations replying with a BlockAck frame (no more than one)
std::map< Mac48Address, AckInfo > stationsReplyingWithNormalAck
Set of stations replying with an Ack frame (no more than one)
WifiDlMuTfMuBar specifies that a DL MU PPDU is followed after a SIFS duration by a MU-BAR Trigger Fra...
std::list< BlockAckReqType > barTypes
BAR types.
std::map< Mac48Address, BlockAckInfo > stationsReplyingWithBlockAck
Set of stations replying with a BlockAck frame.
uint16_t ulLength
the UL Length field of the MU-BAR Trigger Frame
WifiTxVector muBarTxVector
TXVECTOR used to transmit the MU-BAR Trigger Frame.
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.
WifiNoAck specifies that no acknowledgment is required.
WifiNoProtection specifies that no protection method is used.
WifiProtection is an abstract base struct.
Time protectionTime
time required by the protection method
const Method method
protection method
WifiUlMuMultiStaBa specifies that a Basic Trigger Frame is being sent to solicit TB PPDUs that will b...
BlockAckType baType
BlockAck type.
WifiTxVector tbPpduTxVector
TXVECTOR for a TB PPDU.
WifiTxVector multiStaBaTxVector
TXVECTOR for the Multi-STA BlockAck.
std::map< std::pair< Mac48Address, uint8_t >, std::size_t > stationsReceivingMultiStaBa
Map (originator, tid) pairs to the their index in baType.