14#include "ns3/ap-wifi-mac.h"
15#include "ns3/assert.h"
16#include "ns3/ctrl-headers.h"
17#include "ns3/gcr-manager.h"
19#include "ns3/mgt-action-headers.h"
20#include "ns3/recipient-block-ack-agreement.h"
21#include "ns3/snr-tag.h"
22#include "ns3/sta-wifi-mac.h"
23#include "ns3/vht-configuration.h"
24#include "ns3/wifi-mac-queue.h"
25#include "ns3/wifi-net-device.h"
26#include "ns3/wifi-utils.h"
31#undef NS_LOG_APPEND_CONTEXT
32#define NS_LOG_APPEND_CONTEXT WIFI_FEM_NS_LOG_APPEND_CONTEXT
44 static TypeId tid =
TypeId(
"ns3::HtFrameExchangeManager")
46 .AddConstructor<HtFrameExchangeManager>()
47 .SetGroupName(
"Wifi");
102 return m_mac->GetQosTxop(tid)->GetBaManager();
112 if (!
m_mac->GetHtConfiguration() ||
120 else if (
auto agreement = qosTxop->GetBaManager()->GetAgreementAsOriginator(recipient, tid);
121 agreement && !agreement->get().IsReset())
130 uint32_t packets = qosTxop->GetWifiMacQueue()->GetNPackets(queueId);
133 (qosTxop->GetBlockAckThreshold() > 0 && packets >= qosTxop->GetBlockAckThreshold()) ||
136 m_mac->GetVhtConfiguration());
143std::optional<Mac48Address>
147 const auto& groupAddress = header.
GetAddr1();
150 auto qosTxop =
m_mac->GetQosTxop(tid);
151 const auto maxMpduSize =
153 const auto isGcrBa = (
m_apMac->GetGcrManager()->GetRetransmissionPolicy() ==
157 for (
const auto& recipients =
158 m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress);
159 const auto& nextRecipient : recipients)
162 qosTxop->GetBaManager()->GetAgreementAsOriginator(nextRecipient, tid, groupAddress);
163 agreement && !agreement->get().IsReset())
168 const auto packets = qosTxop->GetWifiMacQueue()->GetNPackets(queueId);
169 const auto establish =
171 (qosTxop->GetBlockAckThreshold() > 0 && packets >= qosTxop->GetBlockAckThreshold()) ||
172 (maxMpduSize > 0 && packets > 1));
176 return nextRecipient;
186 uint16_t startingSeq,
190 std::optional<Mac48Address> gcrGroupAddr)
193 << gcrGroupAddr.has_value());
200 hdr.
SetAddr1(addr1 ? *addr1 : dest);
237 GetBaManager(tid)->CreateOriginatorAgreement(reqHdr, dest);
239 packet->AddHeader(reqHdr);
240 packet->AddHeader(actionHdr);
245 uint16_t sequence =
m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader());
246 mpdu->GetHeader().SetSequenceNumber(sequence);
251 if (!
TryAddMpdu(mpdu, txParams, availableTime))
253 NS_LOG_DEBUG(
"Not enough time to send the ADDBA Request frame");
258 m_mac->GetQosTxop(tid)->GetWifiMacQueue()->Enqueue(mpdu);
291 auto tid = reqHdr.
GetTid();
294 auto bufferSize = std::min(
m_mac->GetMpduBufferSize(),
m_mac->GetMaxBaBufferSize(originator));
309 packet->AddHeader(respHdr);
310 packet->AddHeader(actionHdr);
315 originator = *originatorMld;
329 agreement->get().m_inactivityEvent =
355 NS_ASSERT_MSG(it->second,
"The pointer to the pending ADDBA_RESPONSE cannot be null");
366 m_mac->GetQosTxop(tid)->Queue(mpdu);
373 std::optional<Mac48Address> gcrGroupAddr)
375 NS_LOG_FUNCTION(
this << addr << +tid << byOriginator << gcrGroupAddr.has_value());
388 if (gcrGroupAddr.has_value())
399 packet->AddHeader(delbaHdr);
400 packet->AddHeader(actionHdr);
422 if (
auto mpdu =
GetBar(edca->GetAccessCategory());
447 edca->GetBlockAckInactivityTimeout(),
458 edca->GetBlockAckInactivityTimeout(),
470 return SendDataFrame(peekedItem, availableTime, initialFrame);
483 std::optional<uint8_t> optTid,
484 std::optional<Mac48Address> optAddress)
486 NS_LOG_FUNCTION(
this << +ac << optTid.has_value() << optAddress.has_value());
488 "Either both or none of TID and address must be provided");
492 auto queue =
m_mac->GetTxopQueue(ac);
493 queue->WipeAllExpiredMpdus();
502 while ((bar = queue->PeekFirstAvailable(
m_linkId, prevBar)) && bar && bar->GetHeader().IsCtl())
504 if (bar->GetHeader().IsBlockAckReq())
507 bar->GetPacket()->PeekHeader(reqHdr);
510 auto recipientMld =
m_mac->GetMldAddress(recipient);
516 (bar->GetHeader().GetAddr2() ==
m_mac->GetAddress() && recipientMld &&
518 "Cannot use link " << +
m_linkId <<
" to send BAR: " << *bar);
526 <<
" cannot be returned because it is not addressed"
527 " to the given station for the given TID");
532 auto agreement =
m_mac->GetBaAgreementEstablishedAsOriginator(
535 reqHdr.
IsGcr() ? std::optional{reqHdr.GetGcrGroupAddress()} : std::nullopt);
536 if (
const auto isGcrBa =
537 reqHdr.
IsGcr() && (
m_apMac->GetGcrManager()->GetRetransmissionPolicy() ==
539 agreement && reqHdr.
IsGcr() && !isGcrBa)
541 NS_LOG_DEBUG(
"Skip GCR BAR if GCR-BA retransmission policy is not selected");
547 NS_LOG_DEBUG(
"BA agreement with " << recipient <<
" for TID=" << +tid
548 <<
" was torn down");
553 if (
auto seqNo = agreement->get().GetStartingSequence();
558 packet->AddHeader(reqHdr);
559 auto updatedBar =
Create<WifiMpdu>(packet, bar->GetHeader(), bar->GetTimestamp());
560 queue->Replace(bar, updatedBar);
570 if (bar->GetHeader().GetAddr2() ==
m_self && recipientMld)
577 while ((otherBar = queue->PeekByQueueId(queueId, otherBar)))
579 if (otherBar->GetHeader().IsBlockAckReq())
582 otherBar->GetPacket()->PeekHeader(otherReqHdr);
585 queue->Remove(otherBar);
593 if (bar->GetHeader().IsTrigger() && !optAddress && !selectedBar)
604 auto baManager =
m_mac->GetQosTxop(ac)->GetBaManager();
605 for (
const auto& [recipient, tid] : baManager->GetSendBarIfDataQueuedList())
613 if (queue->PeekByTidAndAddress(tid, recipient) &&
616 auto [reqHdr, hdr] =
m_mac->GetQosTxop(ac)->PrepareBlockAckRequest(recipient, tid);
618 pkt->AddHeader(reqHdr);
620 baManager->RemoveFromSendBarIfDataQueuedList(recipient, tid);
621 queue->Enqueue(selectedBar);
629 if (
const auto currAddr1 = selectedBar->GetHeader().GetAddr1();
630 currAddr1 ==
m_mac->GetMldAddress(currAddr1))
638 selectedBar->GetHeader().SetAddr1(addr1);
639 selectedBar->GetHeader().SetAddr2(
m_self);
640 queue->Enqueue(selectedBar);
655 if (!mpdu->GetHeader().IsBlockAckReq())
657 NS_LOG_DEBUG(
"Block Ack Manager returned no frame to send");
669 if (!
TryAddMpdu(mpdu, txParams, availableTime))
671 NS_LOG_DEBUG(
"Not enough time to send the BAR frame returned by the Block Ack Manager");
679 txParams.
m_txVector = blockAcknowledgment->blockAckTxVector;
691 NS_ASSERT(peekedItem && peekedItem->GetHeader().IsQosData() &&
692 !peekedItem->GetHeader().GetAddr1().IsBroadcast() && !peekedItem->IsFragment());
700 edca->GetNextMpdu(
m_linkId, peekedItem, txParams, availableTime, initialFrame);
709 std::vector<Ptr<WifiMpdu>> mpduList =
713 if (mpduList.size() > 1)
741 auto blockAcknowledgment =
static_cast<WifiBlockAck*
>(acknowledgment);
744 blockAcknowledgment->blockAckTxVector,
746 blockAcknowledgment->acknowledgmentTime =
m_phy->
GetSifs() + baTxDuration;
750 auto barBlockAcknowledgment =
static_cast<WifiBarBlockAck*
>(acknowledgment);
753 barBlockAcknowledgment->blockAckReqTxVector,
757 barBlockAcknowledgment->blockAckTxVector,
759 barBlockAcknowledgment->acknowledgmentTime =
785 if (mpdu->GetHeader().IsQosData())
787 uint8_t tid = mpdu->GetHeader().GetQosTid();
790 if (
m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(), tid))
793 edca->GetBaManager()->NotifyGotAck(
m_linkId, mpdu);
798 else if (mpdu->GetHeader().IsAction())
800 auto addr1 = mpdu->GetHeader().GetAddr1();
804 p->RemoveHeader(actionHdr);
810 p->PeekHeader(delBa);
811 auto tid = delBa.
GetTid();
829 p->PeekHeader(addBa);
842 p->PeekHeader(addBa);
843 auto tid = addBa.
GetTid();
848 "Recipient BA agreement {" << address <<
", " << +tid <<
"} not found");
868 NS_LOG_DEBUG(
"Schedule a transmission from Block Ack Manager in a SIFS");
892 if (mpdu->GetHeader().IsQosData())
894 GetBaManager(mpdu->GetHeader().GetQosTid())->NotifyDiscardedMpdu(mpdu);
896 else if (mpdu->GetHeader().IsAction())
899 mpdu->GetPacket()->PeekHeader(actionHdr);
903 const auto tid =
GetTid(mpdu->GetPacket(), mpdu->GetHeader());
904 auto recipient = mpdu->GetHeader().GetAddr1();
908 recipient = *mldAddr;
910 auto p = mpdu->GetPacket()->Copy();
911 p->RemoveHeader(actionHdr);
913 p->PeekHeader(addBa);
918 agreement && agreement->get().IsPending())
922 qosTxop->NotifyOriginatorAgreementNoReply(recipient,
937 if (mpdu->IsQueued())
948 if (mpdu->GetHeader().IsQosData())
950 uint8_t tid = mpdu->GetHeader().GetQosTid();
953 if (
m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(), tid))
956 edca->GetBaManager()->NotifyMissedAck(
m_linkId, mpdu);
968 const auto tids = psdu->GetTids();
969 const auto isGcr =
IsGcr(
m_mac, psdu->GetHeader(0));
970 auto agreementEstablished =
973 ->IsGcrAgreementEstablished(
974 psdu->GetHeader(0).GetAddr1(),
976 m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(
977 psdu->GetHeader(0).GetAddr1()))
978 :
m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), *tids.begin())
981 if (!agreementEstablished)
988 auto mpduIt = psdu->end();
992 std::advance(mpduIt, -1);
994 const WifiMacHeader& hdr = (*mpduIt)->GetOriginal()->GetHeader();
998 agreementEstablished =
1000 psdu->GetHeader(0).GetAddr1(),
1002 m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(
1003 psdu->GetHeader(0).GetAddr1()))
1004 :
m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), tid)
1008 if (!hdr.
IsRetry() && !(*mpduIt)->IsInFlight())
1013 uint16_t currentNextSeq =
m_txMiddle->PeekNextSequenceNumberFor(&hdr);
1017 (*mpduIt)->UnassignSeqNo();
1021 <<
", next sequence "
1023 << hdr.
GetAddr1() <<
",tid=" << +tid <<
" is "
1024 <<
m_txMiddle->PeekNextSequenceNumberFor(&hdr));
1028 }
while (mpduIt != psdu->begin());
1040 const auto singleDurationId = *txParams.
m_acknowledgment->acknowledgmentTime;
1044 return singleDurationId;
1069#ifdef NS3_BUILD_PROFILE_DEBUG
1076 NS_ASSERT(mpdu->GetHeader().IsCtl() || mpdu->IsQueued());
1095 if (mpdu->IsQueued())
1155 NS_ASSERT_MSG(tids.size() <= 1,
"Multi-TID A-MPDUs are not supported");
1163 NS_LOG_DEBUG(
"Prepare groupcast PSDU for retry");
1164 for (const auto& mpdu : *PeekPointer(psdu))
1166 mpdu->ResetInFlight(m_linkId);
1168 if (m_apMac->GetGcrManager()->UseConcealment(mpdu->GetHeader()))
1170 mpdu->GetHeader().SetAddr1(mpdu->begin()->second.GetDestinationAddr());
1172 mpdu->GetHeader().SetRetry();
1178 if (
m_apMac->GetGcrManager()->GetRetransmissionPolicy() ==
1202 m_psdu->SetDuration(GetPsduDurationId(txDuration, m_txParams));
1207 auto blockAcknowledgment =
static_cast<WifiBlockAck*
>(m_txParams.m_acknowledgment.get());
1210 txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
1215 {m_psdu->GetAddr1()},
1219 m_txParams.m_txVector);
1220 m_channelAccessManager->NotifyAckTimeoutStartNow(
timeout);
1224 m_psdu->SetDuration(GetPsduDurationId(txDuration, m_txParams));
1227 const auto tids = m_psdu->GetTids();
1229 "Acknowledgment method incompatible with a Multi-TID A-MPDU");
1230 const auto tid = *tids.begin();
1232 auto edca = m_mac->GetQosTxop(tid);
1233 const auto isGcr =
IsGcr(m_mac, m_psdu->GetHeader(0));
1234 const auto& recipients =
1235 isGcr ? m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(m_psdu->GetAddr1())
1237 std::optional<Mac48Address> gcrGroupAddress{isGcr ? std::optional{m_psdu->GetAddr1()}
1239 for (
const auto& recipient : recipients)
1241 auto [reqHdr, hdr] = edca->PrepareBlockAckRequest(recipient, tid, gcrGroupAddress);
1242 GetBaManager(tid)->ScheduleBar(reqHdr, hdr);
1248 NS_LOG_DEBUG(
"Restore group address of PSDU");
1249 for (const auto& mpdu : *PeekPointer(psdu))
1252 if (m_apMac->GetGcrManager()->UseConcealment(mpdu->GetHeader()))
1254 mpdu->GetHeader().SetAddr1(mpdu->begin()->second.GetDestinationAddr());
1261 TransmissionSucceeded();
1267 NS_ABORT_MSG(
"Unable to handle the selected acknowledgment method ("
1268 << m_txParams.m_acknowledgment.get() <<
")");
1272 if (m_psdu->GetNMpdus() > 1)
1274 ForwardPsduDown(m_psdu, m_txParams.m_txVector);
1278 ForwardMpduDown(*m_psdu->begin(), m_txParams.m_txVector);
1281 if (m_txTimer.IsRunning())
1284 m_sentFrameTo = {m_psdu->GetAddr1()};
1287 if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NONE)
1301 auto& hdr = mpdu->GetHeader();
1303 if (hdr.IsQosData() && hdr.HasData())
1305 auto tid = hdr.GetQosTid();
1306 m_mac->GetQosTxop(tid)->CompleteMpduTx(mpdu);
1317 std::array<std::optional<uint8_t>, 8> queueSizeForTid;
1326 auto edca = m_mac->GetQosTxop(tid);
1328 if (m_mac->GetTypeOfStation() ==
STA && (m_setQosQueueSize || hdr.
IsQosEosp()))
1331 if (!queueSizeForTid[tid].has_value())
1333 queueSizeForTid[tid] =
1334 edca->GetQosQueueSize(tid, mpdu->GetOriginal()->GetHeader().GetAddr1());
1341 if (m_mac->GetTypeOfStation() ==
AP && m_apMac->UseGcr(hdr) &&
1342 m_apMac->GetGcrManager()->UseConcealment(mpdu->GetHeader()))
1344 const auto& gcrConcealmentAddress =
1345 m_apMac->GetGcrManager()->GetGcrConcealmentAddress();
1346 hdr.
SetAddr1(gcrConcealmentAddress);
1351 QosFrameExchangeManager::FinalizeMacHeader(psdu);
1369 NS_LOG_DEBUG(
"Transmitting a PSDU: " << *psdu <<
" TXVECTOR: " << txVector);
1370 FinalizeMacHeader(psdu);
1371 NotifyTxToEdca(psdu);
1372 m_allowedWidth = std::min(m_allowedWidth, txVector.
GetChannelWidth());
1374 if (psdu->IsAggregate())
1379 const auto txDuration = WifiPhy::CalculateTxDuration(psdu, txVector, m_phy->GetPhyBand());
1380 SetTxNav(*psdu->begin(), txDuration);
1382 m_phy->Send(psdu, txVector);
1388 Time ppduDurationLimit)
const
1403 if (mpdu->GetHeader().IsQosData())
1405 tid = mpdu->GetHeader().GetQosTid();
1413 NS_ABORT_MSG(
"Cannot aggregate a non-QoS data frame to an A-MPDU that does"
1414 " not contain any QoS data frame");
1419 if (!IsWithinAmpduSizeLimit(ampduSize, receiver, tid, modulation))
1425 return IsWithinSizeAndTimeLimits(ampduSize, receiver, txParams, ppduDurationLimit);
1429HtFrameExchangeManager::IsWithinAmpduSizeLimit(
uint32_t ampduSize,
1436 uint32_t maxAmpduSize = m_mpduAggregator->GetMaxAmpduSize(receiver, tid, modulation);
1438 if (maxAmpduSize == 0)
1444 if (ampduSize > maxAmpduSize)
1446 NS_LOG_DEBUG(
"the frame does not meet the constraint on max A-MPDU size (" << maxAmpduSize
1456 Time availableTime)
const
1458 NS_ASSERT(msdu && msdu->GetHeader().IsQosData());
1464 UpdateTxDuration(msdu->GetHeader().GetAddr1(), txParams);
1468 auto protectionTime = txParams.
m_protection->protectionTime;
1470 std::unique_ptr<WifiProtection> protection;
1471 protection = GetProtectionManager()->TryAggregateMsdu(msdu, txParams);
1472 bool protectionSwapped =
false;
1477 CalculateProtectionTime(protection.get());
1478 protectionTime = protection->protectionTime;
1482 protectionSwapped =
true;
1490 std::unique_ptr<WifiAcknowledgment> acknowledgment;
1491 acknowledgment = GetAckManager()->TryAggregateMsdu(msdu, txParams);
1492 bool acknowledgmentSwapped =
false;
1497 CalculateAcknowledgmentTime(acknowledgment.get());
1498 acknowledgmentTime = acknowledgment->acknowledgmentTime;
1502 acknowledgmentSwapped =
true;
1504 NS_ASSERT(acknowledgmentTime.has_value());
1506 Time ppduDurationLimit = Time::Min();
1507 if (availableTime != Time::Min())
1509 ppduDurationLimit = availableTime - *protectionTime - *acknowledgmentTime;
1512 if (!IsWithinLimitsIfAggregateMsdu(msdu, txParams, ppduDurationLimit))
1518 if (protectionSwapped)
1522 if (acknowledgmentSwapped)
1535 Time ppduDurationLimit)
const
1537 NS_ASSERT(msdu && msdu->GetHeader().IsQosData());
1540 auto receiver = msdu->GetHeader().GetAddr1();
1541 auto tid = msdu->GetHeader().GetQosTid();
1544 NS_ASSERT_MSG(psduInfo,
"No PSDU info for receiver " << receiver);
1547 uint16_t maxAmsduSize = m_msduAggregator->GetMaxAmsduSize(receiver, tid, modulation);
1549 if (maxAmsduSize == 0)
1555 if (psduInfo->amsduSize > maxAmsduSize)
1557 NS_LOG_DEBUG(
"No other MSDU can be aggregated: maximum A-MSDU size (" << maxAmsduSize
1564 auto ampduSize = txParams.
GetSize(receiver);
1570 if (!IsWithinAmpduSizeLimit(ampduSize, receiver, tid, modulation))
1576 return IsWithinSizeAndTimeLimits(ampduSize, receiver, txParams, ppduDurationLimit);
1584 GetWifiRemoteStationManager()->ReportDataFailed(*psdu->begin());
1586 MissedBlockAck(psdu, txVector);
1589 TransmissionFailed();
1597 auto recipient = psdu->GetAddr1();
1598 auto recipientMld = GetWifiRemoteStationManager()->GetMldAddress(recipient).value_or(recipient);
1601 std::optional<Mac48Address> gcrGroupAddress;
1603 if (psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsBlockAckReq())
1607 psdu->GetPayload(0)->PeekHeader(baReqHdr);
1609 if (baReqHdr.
IsGcr())
1617 std::set<uint8_t> tids = psdu->GetTids();
1618 NS_ABORT_MSG_IF(tids.size() > 1,
"Multi-TID A-MPDUs not handled here");
1620 tid = *tids.begin();
1622 GetWifiRemoteStationManager()
1623 ->ReportAmpduTxStatus(recipient, 0, psdu->GetNMpdus(), 0, 0, txVector);
1625 if (
auto droppedMpdu = DropMpduIfRetryLimitReached(psdu))
1628 GetWifiRemoteStationManager()->ReportFinalDataFailed(droppedMpdu);
1634 if (edca->UseExplicitBarAfterMissedBlockAck() || isBar)
1637 const auto retransmitBar =
1638 gcrGroupAddress.has_value()
1639 ? GetBaManager(tid)->NeedGcrBarRetransmission(gcrGroupAddress.value(),
1642 : GetBaManager(tid)->NeedBarRetransmission(tid, recipientMld);
1645 NS_LOG_DEBUG(
"Missed Block Ack, transmit a BlockAckReq");
1658 psdu->GetHeader(0).SetRetry();
1663 auto [reqHdr, hdr] = edca->PrepareBlockAckRequest(recipient, tid);
1664 GetBaManager(tid)->ScheduleBar(reqHdr, hdr);
1669 NS_LOG_DEBUG(
"Missed Block Ack, do not transmit a BlockAckReq");
1676 if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid))
1680 GetBaManager(tid)->AddToSendBarIfDataQueuedList(recipientMld, tid);
1687 GetBaManager(tid)->NotifyMissedBlockAck(m_linkId, recipientMld, tid);
1696 std::optional<Mac48Address> gcrGroupAddr)
1698 NS_LOG_FUNCTION(
this << durationId << blockAckTxVector << rxSnr << gcrGroupAddr.has_value());
1702 auto addr1 = agreement.
GetPeer();
1703 if (
auto originator = GetWifiRemoteStationManager()->GetAffiliatedStaAddress(addr1))
1705 addr1 = *originator;
1714 if (gcrGroupAddr.has_value())
1722 packet->AddHeader(blockAck);
1723 Ptr<WifiPsdu> psdu = GetWifiPsdu(Create<WifiMpdu>(packet, hdr), blockAckTxVector);
1731 Time baDurationId = durationId - m_phy->GetSifs() -
1732 WifiPhy::CalculateTxDuration(psdu, blockAckTxVector, m_phy->GetPhyBand());
1738 psdu->GetHeader(0).SetDuration(baDurationId);
1742 psdu->GetPayload(0)->AddPacketTag(tag);
1744 ForwardPsduDown(psdu, blockAckTxVector);
1753 NS_LOG_FUNCTION(
this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1756 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
1758 double rxSnr = rxSignalInfo.
snr;
1763 if (hdr.
IsCts() && m_txTimer.IsRunning() &&
1764 m_txTimer.GetReason() == WifiTxTimer::WAIT_CTS && m_psdu)
1773 mpdu->GetPacket()->PeekPacketTag(tag);
1774 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
1775 GetWifiRemoteStationManager()->ReportRtsOk(m_psdu->GetHeader(0),
1781 m_channelAccessManager->NotifyCtsTimeoutResetNow();
1782 ProtectionCompleted();
1784 else if (hdr.
IsBlockAck() && m_txTimer.IsRunning() &&
1785 m_txTimer.GetReason() == WifiTxTimer::WAIT_BLOCK_ACK && hdr.
GetAddr1() == m_self)
1789 m_txTimer.GotResponseFrom(sender);
1792 mpdu->GetPacket()->PeekPacketTag(tag);
1796 mpdu->GetPacket()->PeekHeader(blockAck);
1798 if (blockAck.
IsGcr())
1800 const auto& gcrMembers = m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(
1802 const auto ret = GetBaManager(tid)->NotifyGotGcrBlockAck(
1805 m_mac->GetMldAddress(sender).value_or(sender),
1808 if (ret.has_value())
1810 for (
const auto& sender : gcrMembers)
1812 GetWifiRemoteStationManager()->ReportAmpduTxStatus(sender,
1817 m_txParams.m_txVector);
1823 const auto [nSuccessful, nFailed] = GetBaManager(tid)->NotifyGotBlockAck(
1826 m_mac->GetMldAddress(sender).value_or(sender),
1829 GetWifiRemoteStationManager()->ReportAmpduTxStatus(sender,
1834 m_txParams.m_txVector);
1839 m_channelAccessManager->NotifyAckTimeoutResetNow();
1842 m_edca->ResetCw(m_linkId);
1845 if (m_psdu && m_psdu->GetNMpdus() == 1 && m_psdu->GetHeader(0).IsBlockAckReq())
1847 DequeuePsdu(m_psdu);
1850 TransmissionSucceeded();
1861 mpdu->GetPacket()->PeekHeader(blockAckReq);
1865 auto agreement = m_mac->GetBaAgreementEstablishedAsRecipient(
1868 blockAckReq.
IsGcr() ? std::optional{blockAckReq.GetGcrGroupAddress()}
1872 NS_LOG_DEBUG(
"There's not a valid agreement for this BlockAckReq");
1876 GetBaManager(tid)->NotifyGotBlockAckRequest(
1877 m_mac->GetMldAddress(sender).value_or(sender),
1880 blockAckReq.
IsGcr() ? std::optional{blockAckReq.GetGcrGroupAddress()}
1884 Simulator::Schedule(
1886 &HtFrameExchangeManager::SendBlockAck,
1890 GetWifiRemoteStationManager()->GetBlockAckTxVector(sender, txVector),
1892 blockAckReq.
IsGcr() ? std::optional{blockAckReq.GetGcrGroupAddress()}
1898 QosFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
1905 ((hdr.
GetAddr1() == m_self) || (isGroup && (inAmpdu || !mpdu->GetHeader().IsQosNoAck()))))
1909 auto agreement = m_mac->GetBaAgreementEstablishedAsRecipient(
1912 isGroup ? std::optional{hdr.
IsQosAmsdu() ? mpdu->begin()->second.GetDestinationAddr()
1920 GetBaManager(tid)->NotifyGotMpdu(mpdu);
1925 Simulator::Schedule(m_phy->GetSifs(),
1926 &HtFrameExchangeManager::SendNormalAck,
1940 ReceiveMgtAction(mpdu, txVector);
1944 !m_mac->GetRobustAVStreamingSupported())
1949 QosFrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
1957 NS_ASSERT(mpdu->GetHeader().IsAction());
1958 const auto from = mpdu->GetOriginal()->GetHeader().GetAddr2();
1961 auto packet = mpdu->GetPacket()->Copy();
1962 packet->RemoveHeader(actionHdr);
1965 const auto ackTxVector =
1966 GetWifiRemoteStationManager()->GetAckTxVector(mpdu->GetHeader().GetAddr2(), txVector);
1967 const auto ackTxTime =
1968 WifiPhy::CalculateTxDuration(
GetAckSize(), ackTxVector, m_phy->GetPhyBand());
1972 case WifiActionHeader::BLOCK_ACK:
1976 case WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST: {
1978 packet->RemoveHeader(reqHdr);
1983 Simulator::Schedule(m_phy->GetSifs() + ackTxTime,
1984 &HtFrameExchangeManager::SendAddBaResponse,
1991 case WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE: {
1993 packet->RemoveHeader(respHdr);
1998 Simulator::Schedule(m_phy->GetSifs() + ackTxTime, [=,
this]() {
1999 const auto recipient =
2000 GetWifiRemoteStationManager()->GetMldAddress(from).value_or(from);
2001 m_mac->GetQosTxop(respHdr.GetTid())->GotAddBaResponse(respHdr, recipient);
2002 GetBaManager(respHdr.GetTid())
2003 ->SetBlockAckInactivityCallback(
2004 MakeCallback(&HtFrameExchangeManager::SendDelbaFrame, this));
2009 case WifiActionHeader::BLOCK_ACK_DELBA: {
2011 packet->RemoveHeader(delBaHdr);
2012 auto recipient = GetWifiRemoteStationManager()->GetMldAddress(from).value_or(from);
2020 GetBaManager(delBaHdr.
GetTid())
2021 ->DestroyRecipientAgreement(recipient,
2030 m_mac->GetQosTxop(delBaHdr.
GetTid())->GotDelBaFrame(&delBaHdr, recipient);
2036 NS_FATAL_ERROR(
"Unsupported Action field in Block Ack Action frame");
2048 const std::vector<bool>& perMpduStatus)
2051 this << *psdu << rxSignalInfo << txVector << perMpduStatus.size()
2052 << std::all_of(perMpduStatus.begin(), perMpduStatus.end(), [](
bool v) { return v; }));
2054 std::set<uint8_t> tids = psdu->GetTids();
2057 if (tids.size() == 1)
2059 uint8_t tid = *tids.begin();
2063 if (ackPolicy == WifiMacHeader::NORMAL_ACK)
2067 auto agreement = m_mac->GetBaAgreementEstablishedAsRecipient(psdu->GetAddr2(), tid);
2070 Simulator::Schedule(
2072 &HtFrameExchangeManager::SendBlockAck,
2075 psdu->GetDuration(),
2076 GetWifiRemoteStationManager()->GetBlockAckTxVector(psdu->GetAddr2(), txVector),
2080 else if (psdu->GetAddr1().IsGroup() && (ackPolicy == WifiMacHeader::NO_ACK))
2083 m_flushGroupcastMpdusEvent.Cancel();
2095 const auto startSeq = psdu->GetHeader(0).GetSequenceNumber();
2096 const auto groupAddress = psdu->GetHeader(0).IsQosAmsdu()
2097 ? (*psdu->begin())->begin()->second.GetDestinationAddr()
2099 FlushGroupcastMpdus(groupAddress, psdu->GetAddr2(), tid, startSeq);
2107 const auto stopSeq = (startSeq + perMpduStatus.size()) % 4096;
2108 const auto maxDelay = m_mac->GetQosTxop(tid)->GetWifiMacQueue()->GetMaxDelay();
2109 m_flushGroupcastMpdusEvent =
2110 Simulator::Schedule(maxDelay,
2111 &HtFrameExchangeManager::FlushGroupcastMpdus,
2122HtFrameExchangeManager::FlushGroupcastMpdus(
const Mac48Address& groupAddress,
2129 GetBaManager(tid)->NotifyGotBlockAckRequest(originator, tid, seq, groupAddress);
2136 const auto tid = mpdu->GetHeader().GetQosTid();
2137 const auto groupAddress = mpdu->GetHeader().GetAddr1();
2138 if (!GetBaManager(tid)->IsGcrAgreementEstablished(
2141 m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress)))
2145 GetBaManager(tid)->NotifyLastGcrUrTx(
2147 m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress));
BlockAckType GetBlockAckType() const
Get the type of the Block Acks sent by the recipient of this agreement.
uint8_t GetTid() const
Return the Traffic ID (TID).
Mac48Address GetPeer() const
Return the peer address.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsPending() const
This method is syntactic sugar for !IsExpired().
std::set< Mac48Address > m_sentRtsTo
the STA(s) which we sent an RTS to (waiting for CTS)
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
bool m_protectedIfResponded
whether a STA is assumed to be protected if replied to a frame requiring acknowledgment
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the MAC layer to use.
void SendMpduWithProtection(Ptr< WifiMpdu > mpdu, WifiTxParameters &txParams)
Send an MPDU with the given TX parameters (with the specified protection).
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
virtual void CalculateAcknowledgmentTime(WifiAcknowledgment *acknowledgment) const
Calculate the time required to acknowledge a frame according to the given acknowledgment method.
Ptr< MacTxMiddle > m_txMiddle
the MAC TX Middle on this station
Mac48Address m_self
the MAC address of this device
virtual void StartProtection(const WifiTxParameters &txParams)
Start the protection mechanism indicated by the given TX parameters.
virtual void NotifyPacketDiscarded(Ptr< const WifiMpdu > mpdu)
Pass the given MPDU, discarded because of the max retry limit was reached, to the MPDU dropped callba...
std::set< Mac48Address > m_protectedStas
STAs that have replied to an RTS in this TXOP.
virtual void RetransmitMpduAfterMissedAck(Ptr< WifiMpdu > mpdu) const
Retransmit an MPDU that was not acknowledged.
virtual void ProtectionCompleted()
Transmit prepared frame immediately, if no protection was used, or in a SIFS, if protection was compl...
virtual void NotifyReceivedNormalAck(Ptr< WifiMpdu > mpdu)
Notify other components that an MPDU was acknowledged.
virtual void CtsTimeout(Ptr< WifiMpdu > rts, const WifiTxVector &txVector)
Called when the CTS timeout expires.
void DoCtsTimeout(const WifiPsduMap &psduMap)
Take required actions when the CTS timer fired after sending an (MU-)RTS to protect the given PSDU ma...
Time m_txNav
the TXNAV timer
virtual void DequeueMpdu(Ptr< const WifiMpdu > mpdu)
Dequeue the given MPDU from the queue in which it is stored.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
Ptr< WifiPhy > m_phy
the PHY layer on this station
virtual void ReleaseSequenceNumbers(Ptr< const WifiPsdu > psdu) const
Make the sequence numbers of MPDUs included in the given PSDU available again if the MPDUs have never...
std::set< Mac48Address > m_sentFrameTo
the STA(s) to which we sent a frame requesting a response
Ptr< ApWifiMac > m_apMac
AP MAC layer pointer (null if not an AP)
Mac48Address m_bssid
BSSID address (Mac48Address)
virtual bool StartTransmission(Ptr< Txop > dcf, MHz_u allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
MHz_u m_allowedWidth
the allowed width for the current transmission
std::unordered_set< Mac48Address, WifiAddressHash > GcrMembers
MAC addresses of member STAs of a GCR group.
HtFrameExchangeManager handles the frame exchange sequences for HT stations.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
std::map< AgreementKey, Ptr< WifiMpdu > > m_pendingAddBaResp
pending ADDBA_RESPONSE frames indexed by agreement key
void SendAddBaResponse(const MgtAddBaRequestHeader &reqHdr, Mac48Address originator)
This method can be called to accept a received ADDBA Request.
void CtsTimeout(Ptr< WifiMpdu > rts, const WifiTxVector &txVector) override
Called when the CTS timeout expires.
Ptr< WifiPsdu > m_psdu
the A-MPDU being transmitted
Ptr< BlockAckManager > GetBaManager(uint8_t tid) const
Get the Block Ack Manager handling the given TID.
virtual Ptr< WifiPsdu > GetWifiPsdu(Ptr< WifiMpdu > mpdu, const WifiTxVector &txVector) const
Get a PSDU containing the given MPDU.
virtual void BlockAckTimeout(Ptr< WifiPsdu > psdu, const WifiTxVector &txVector)
Called when the BlockAck 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.
virtual bool NeedSetupBlockAck(Mac48Address recipient, uint8_t tid)
A Block Ack agreement needs to be established with the given recipient for the given TID if it does n...
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...
Ptr< MpduAggregator > GetMpduAggregator() const
Returns the aggregator used to construct A-MPDU subframes.
void SetWifiMac(const Ptr< WifiMac > mac) override
Set the MAC layer to use.
virtual std::optional< Mac48Address > NeedSetupGcrBlockAck(const WifiMacHeader &header)
A Block Ack agreement needs to be established prior to the transmission of a groupcast data packet us...
bool SendAddBaRequest(Mac48Address recipient, uint8_t tid, uint16_t startingSeq, uint16_t timeout, bool immediateBAck, Time availableTime, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
Sends an ADDBA Request to establish a block ack agreement with STA addressed by recipient for TID tid...
void ProtectionCompleted() override
Transmit prepared frame immediately, if no protection was used, or in a SIFS, if protection was compl...
void ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector) override
Forward an MPDU down to the PHY layer.
Ptr< MsduAggregator > GetMsduAggregator() const
Returns the aggregator used to construct A-MSDU subframes.
void SendPsduWithProtection(Ptr< WifiPsdu > psdu, WifiTxParameters &txParams)
Send a PSDU (A-MPDU or BlockAckReq frame) requesting a BlockAck frame or a BlockAckReq frame followed...
void NotifyReceivedNormalAck(Ptr< WifiMpdu > mpdu) override
Notify other components that an MPDU was acknowledged.
void RetransmitMpduAfterMissedAck(Ptr< WifiMpdu > mpdu) const override
Retransmit an MPDU that was not acknowledged.
void DoDispose() override
Destructor implementation.
static TypeId GetTypeId()
Get the type ID.
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...
WifiTxParameters m_txParams
the TX parameters for the current frame
void SendPsdu()
Send the current PSDU, which can be acknowledged by a BlockAck frame or followed by a BlockAckReq fra...
virtual bool SendDataFrame(Ptr< WifiMpdu > peekedItem, Time availableTime, bool initialFrame)
Given a non-broadcast QoS data frame, prepare the PSDU to transmit by attempting A-MSDU and A-MPDU ag...
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator, std::optional< Mac48Address > gcrGroupAddr)
Sends DELBA frame to cancel a block ack agreement with STA addressed by addr for TID tid.
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 CalculateAcknowledgmentTime(WifiAcknowledgment *acknowledgment) const override
Calculate the time required to acknowledge a frame according to the given acknowledgment method.
~HtFrameExchangeManager() override
EventId m_flushGroupcastMpdusEvent
the event to flush pending groupcast MPDUs from previously received A-MPDU
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...
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef (MAC address and TID)
void NotifyLastGcrUrTx(Ptr< const WifiMpdu > mpdu) override
Notify the last (re)transmission of a groupcast MPDU using the GCR-UR service.
uint16_t GetBaAgreementStartingSequenceNumber(const WifiMacHeader &header)
Retrieve the starting sequence number for a BA agreement to be established.
Smart pointer class similar to boost::intrusive_ptr.
QosFrameExchangeManager handles the frame exchange sequences for QoS stations.
virtual bool StartFrameExchange(Ptr< QosTxop > edca, Time availableTime, bool initialFrame)
Start a frame exchange (including protection frames and acknowledgment frames as needed) that fits wi...
Ptr< QosTxop > m_edca
the EDCAF that gained channel access
virtual Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
Time m_singleExchangeProtectionSurplus
additional time to protect beyond end of the immediate frame exchange in case of non-zero TXOP limit ...
bool TryAddMpdu(Ptr< const WifiMpdu > mpdu, WifiTxParameters &txParams, Time availableTime) const
Recompute the protection and acknowledgment methods to use if the given MPDU is added to the frame be...
bool m_protectSingleExchange
true if the Duration/ID field in frames establishing protection only covers the immediate frame excha...
void DoDispose() override
Destructor implementation.
AcIndex GetAccessCategory() const
Get the access category of this object.
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
Callback when ADDBA response is not received after timeout.
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
void ResetBa(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
Reset BA agreement after BA negotiation failed.
Maintains the scoreboard and the receive reordering buffer used by a recipient of a Block Ack agreeme...
void FillBlockAckBitmap(CtrlBAckResponseHeader &blockAckHeader, std::size_t index=0) const
Set the Starting Sequence Number subfield of the Block Ack Starting Sequence Control subfield of the ...
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.
void Set(double snr)
Set the SNR to the given value.
double Get() const
Return the SNR value.
Status code for association response.
void SetSuccess()
Set success bit to 0 (success).
Simulation virtual time values and global simulation resolution.
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
bool IsZero() const
Exactly equivalent to t == 0.
Time GetTxopLimit() const
Return the TXOP limit.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
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.
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.
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.
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
uint32_t GetSize() const
Return the size of the PSDU in bytes.
WifiMacHeader::QosAckPolicy GetAckPolicyForTid(uint8_t tid) const
Get the QoS Ack Policy of the QoS Data frames included in the PSDU that have the given TID.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::optional< Time > m_txDuration
TX duration of the frame.
std::unique_ptr< WifiProtection > m_protection
protection method
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
const PsduInfo * GetPsduInfo(Mac48Address receiver) const
Get a pointer to the information about the PSDU addressed to the given receiver, if present,...
void UndoAddMpdu()
Undo the addition of the last MPDU added by calling AddMpdu().
bool LastAddedIsFirstMpdu(Mac48Address receiver) const
Check if the last added MPDU is the first MPDU for the given receiver.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void AggregateMsdu(Ptr< const WifiMpdu > msdu)
Record that an MSDU is being aggregated to the last MPDU added to the frame that hase the same receiv...
void Clear()
Reset the TX parameters.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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 SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
MHz_u GetChannelWidth() const
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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_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 ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
This function is useful to get traffic id of different packet types.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
bool IsGroupcast(const Mac48Address &adr)
Check whether a MAC destination address corresponds to a groupcast transmission.
uint32_t GetBlockAckRequestSize(BlockAckReqType type)
Return the total BlockAckRequest size (including FCS trailer).
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
uint32_t GetAckSize()
Return the total Ack size (including FCS trailer).
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
bool IsGcr(Ptr< WifiMac > mac, const WifiMacHeader &hdr)
Return whether a given packet is transmitted using the GCR service.
RxSignalInfo structure containing info on the received signal.
double snr
SNR in linear scale.
WifiAcknowledgment is an abstract base struct.
const Method method
acknowledgment method
WifiBarBlockAck specifies that a BlockAckReq is sent to solicit a Block Ack response.
WifiBlockAck specifies that acknowledgment via Block Ack is required.
information about the frame being prepared for a specific receiver
std::map< uint8_t, std::set< uint16_t > > seqNumbers
set of the sequence numbers of the MPDUs added for each TID
uint32_t ampduSize
the size in bytes of the A-MPDU if multiple MPDUs have been added, and zero otherwise