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,
 
  745                                         m_phy->GetPhyBand());
 
  746        blockAcknowledgment->acknowledgmentTime = 
m_phy->GetSifs() + baTxDuration;
 
  750        auto barBlockAcknowledgment = 
static_cast<WifiBarBlockAck*
>(acknowledgment);
 
  753                                         barBlockAcknowledgment->blockAckReqTxVector,
 
  754                                         m_phy->GetPhyBand());
 
  757                                         barBlockAcknowledgment->blockAckTxVector,
 
  758                                         m_phy->GetPhyBand());
 
  759        barBlockAcknowledgment->acknowledgmentTime =
 
  760            2 * 
m_phy->GetSifs() + barTxDuration + baTxDuration;
 
 
  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());
 
 1085    if (!
m_txParams.m_acknowledgment->acknowledgmentTime.has_value())
 
 1095        if (mpdu->IsQueued())
 
 
 1154        std::set<uint8_t> tids = 
m_psdu->GetTids();
 
 1155        NS_ASSERT_MSG(tids.size() <= 1, 
"Multi-TID A-MPDUs are not supported");
 
 1159            if (
m_apMac->GetGcrManager()->KeepGroupcastQueued(*
m_psdu->begin()))
 
 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);
 
 1331                if (!queueSizeForTid[tid].has_value())
 
 1333                    queueSizeForTid[tid] =
 
 1334                        edca->GetQosQueueSize(tid, mpdu->GetOriginal()->GetHeader().GetAddr1());
 
 1342                m_apMac->GetGcrManager()->UseConcealment(mpdu->GetHeader()))
 
 1344                const auto& gcrConcealmentAddress =
 
 1345                    m_apMac->GetGcrManager()->GetGcrConcealmentAddress();
 
 1346                hdr.
SetAddr1(gcrConcealmentAddress);
 
 
 1369    NS_LOG_DEBUG(
"Transmitting a PSDU: " << *psdu << 
" TXVECTOR: " << txVector);
 
 1374    if (psdu->IsAggregate())
 
 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");
 
 
 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());
 
 1468    auto protectionTime = txParams.
m_protection->protectionTime;
 
 1470    std::unique_ptr<WifiProtection> protection;
 
 1472    bool protectionSwapped = 
false;
 
 1478        protectionTime = protection->protectionTime;
 
 1482        protectionSwapped = 
true;
 
 1490    std::unique_ptr<WifiAcknowledgment> acknowledgment;
 
 1491    acknowledgment = 
GetAckManager()->TryAggregateMsdu(msdu, txParams);
 
 1492    bool acknowledgmentSwapped = 
false;
 
 1498        acknowledgmentTime = acknowledgment->acknowledgmentTime;
 
 1502        acknowledgmentSwapped = 
true;
 
 1504    NS_ASSERT(acknowledgmentTime.has_value());
 
 1509        ppduDurationLimit = availableTime - *protectionTime - *acknowledgmentTime;
 
 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);
 
 
 1597    auto recipient = psdu->GetAddr1();
 
 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();
 
 1623            ->ReportAmpduTxStatus(recipient, 0, psdu->GetNMpdus(), 0, 0, txVector);
 
 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);
 
 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);
 
 
 1696                                     std::optional<Mac48Address> gcrGroupAddr)
 
 1698    NS_LOG_FUNCTION(
this << durationId << blockAckTxVector << rxSnr << gcrGroupAddr.has_value());
 
 1702    auto addr1 = agreement.
GetPeer();
 
 1705        addr1 = *originator;
 
 1714    if (gcrGroupAddr.has_value())
 
 1722    packet->AddHeader(blockAck);
 
 1731    Time baDurationId = durationId - 
m_phy->GetSifs() -
 
 1738    psdu->GetHeader(0).SetDuration(baDurationId);
 
 1742    psdu->GetPayload(0)->AddPacketTag(tag);
 
 
 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;
 
 1773            mpdu->GetPacket()->PeekPacketTag(tag);
 
 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)
 
 1823                const auto [nSuccessful, nFailed] = 
GetBaManager(tid)->NotifyGotBlockAck(
 
 1826                    m_mac->GetMldAddress(sender).value_or(sender),
 
 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");
 
 1877                m_mac->GetMldAddress(sender).value_or(sender),
 
 1880                blockAckReq.
IsGcr() ? std::optional{blockAckReq.GetGcrGroupAddress()}
 
 1892                blockAckReq.
IsGcr() ? std::optional{blockAckReq.GetGcrGroupAddress()}
 
 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()
 
 1944        !
m_mac->GetRobustAVStreamingSupported())
 
 
 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 =
 
 1967    const auto ackTxTime =
 
 1978            packet->RemoveHeader(reqHdr);
 
 1993            packet->RemoveHeader(respHdr);
 
 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));
 
 2011            packet->RemoveHeader(delBaHdr);
 
 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();
 
 2067            auto agreement = 
m_mac->GetBaAgreementEstablishedAsRecipient(psdu->GetAddr2(), tid);
 
 2075                psdu->GetDuration(),
 
 2095            const auto startSeq = psdu->GetHeader(0).GetSequenceNumber();
 
 2096            const auto groupAddress = psdu->GetHeader(0).IsQosAmsdu()
 
 2097                                          ? (*psdu->begin())->begin()->second.GetDestinationAddr()
 
 2107            const auto stopSeq = (startSeq + perMpduStatus.size()) % 4096;
 
 2108            const auto maxDelay = 
m_mac->GetQosTxop(tid)->GetWifiMacQueue()->GetMaxDelay();
 
 
 2129    GetBaManager(tid)->NotifyGotBlockAckRequest(originator, tid, seq, groupAddress);
 
 
 2136    const auto tid = mpdu->GetHeader().GetQosTid();
 
 2137    const auto groupAddress = mpdu->GetHeader().GetAddr1();
 
 2141            m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress)))
 
 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.
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
void SetTxNav(Ptr< const WifiMpdu > mpdu, const Time &txDuration)
Set the TXNAV upon sending an MPDU.
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
void UpdateTxDuration(Mac48Address receiver, WifiTxParameters &txParams) const
Update the TX duration field of the given TX parameters after that the PSDU addressed to the given re...
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
void SendNormalAck(const WifiMacHeader &hdr, const WifiTxVector &dataTxVector, double dataSnr)
Send Normal Ack.
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...
WifiTxTimer m_txTimer
the timer set upon frame transmission
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 CalculateProtectionTime(WifiProtection *protection) const
Calculate the time required to protect a frame according to the given protection method.
Ptr< WifiAckManager > GetAckManager() const
Get the Acknowledgment Manager used by this node.
virtual void DequeueMpdu(Ptr< const WifiMpdu > mpdu)
Dequeue the given MPDU from the queue in which it is stored.
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
Ptr< WifiPhy > m_phy
the PHY layer on this station
Ptr< WifiMpdu > DropMpduIfRetryLimitReached(Ptr< WifiPsdu > psdu)
Wrapper for the GetMpdusToDropOnTxFailure function of the remote station manager that additionally dr...
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 void FinalizeMacHeader(Ptr< const WifiPsdu > psdu)
Finalize the MAC header of the MPDUs in the given PSDU before transmission.
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
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.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
std::map< AgreementKey, Ptr< WifiMpdu > > m_pendingAddBaResp
pending ADDBA_RESPONSE frames indexed by agreement key
void FlushGroupcastMpdus(const Mac48Address &groupAddress, const Mac48Address &originator, uint8_t tid, uint16_t seq)
Perform required actions to ensure the receiver window is flushed when a groupcast A-MPDU is received...
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 FinalizeMacHeader(Ptr< const WifiPsdu > psdu) override
Finalize the MAC header of the MPDUs in the given PSDU before transmission.
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.
virtual bool IsWithinLimitsIfAggregateMsdu(Ptr< const WifiMpdu > msdu, const WifiTxParameters &txParams, Time ppduDurationLimit) const
Check if the PSDU obtained by aggregating the given MSDU to the PSDU specified by the given TX parame...
virtual bool IsWithinAmpduSizeLimit(uint32_t ampduSize, Mac48Address receiver, uint8_t tid, WifiModulationClass modulation) const
Check whether an A-MPDU of the given size meets the constraint on the maximum size for A-MPDUs sent t...
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 EndReceiveAmpdu(Ptr< const WifiPsdu > psdu, const RxSignalInfo &rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &perMpduStatus) override
This method is called when the reception of an A-MPDU including multiple MPDUs is completed.
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
bool IsWithinLimitsIfAddMpdu(Ptr< const WifiMpdu > mpdu, const WifiTxParameters &txParams, Time ppduDurationLimit) const override
Check if the PSDU obtained by aggregating the given MPDU to the PSDU specified by the given TX parame...
void SendPsdu()
Send the current PSDU, which can be acknowledged by a BlockAck frame or followed by a BlockAckReq fra...
void ReceiveMgtAction(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector)
Process a received management action frame that relates to Block Ack agreement.
virtual bool TryAggregateMsdu(Ptr< const WifiMpdu > msdu, WifiTxParameters &txParams, Time availableTime) const
Check if aggregating an MSDU to the current MPDU (as specified by the given TX parameters) does not v...
virtual void NotifyTxToEdca(Ptr< const WifiPsdu > psdu) const
Notify the transmission of the given PSDU to the EDCAF associated with the AC the PSDU belongs to.
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.
virtual void MissedBlockAck(Ptr< WifiPsdu > psdu, const WifiTxVector &txVector)
Take necessary actions when a BlockAck is missed, such as scheduling a BlockAckReq frame or the retra...
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...
void SendBlockAck(const RecipientBlockAckAgreement &agreement, Time durationId, WifiTxVector &blockAckTxVector, double rxSnr, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
Create a BlockAck frame with header equal to blockAck and start its transmission.
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.
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
QosFrameExchangeManager()
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
void TransmissionFailed(bool forceCurrentCw=false) override
Take necessary actions upon a transmission failure.
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.
bool m_setQosQueueSize
whether to set the Queue Size subfield of the QoS Control field of QoS data frames
virtual bool IsWithinSizeAndTimeLimits(uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters &txParams, Time ppduDurationLimit) const
Check whether the transmission time of the frame being built (as described by the given TX parameters...
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.
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
Callback when ADDBA response is not received after timeout.
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.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
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.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
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...
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::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).
std::tuple< WifiContainerQueueType, WifiRcvAddr, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
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