14#include "ns3/assert.h"
15#include "ns3/ctrl-headers.h"
17#include "ns3/mgt-action-headers.h"
18#include "ns3/recipient-block-ack-agreement.h"
19#include "ns3/snr-tag.h"
20#include "ns3/sta-wifi-mac.h"
21#include "ns3/vht-configuration.h"
22#include "ns3/wifi-mac-queue.h"
23#include "ns3/wifi-net-device.h"
24#include "ns3/wifi-utils.h"
29#undef NS_LOG_APPEND_CONTEXT
30#define NS_LOG_APPEND_CONTEXT WIFI_FEM_NS_LOG_APPEND_CONTEXT
42 static TypeId tid =
TypeId(
"ns3::HtFrameExchangeManager")
44 .AddConstructor<HtFrameExchangeManager>()
45 .SetGroupName(
"Wifi");
96 return m_mac->GetQosTxop(tid)->GetBaManager();
106 if (!
m_mac->GetHtConfiguration() ||
114 else if (
auto agreement = qosTxop->GetBaManager()->GetAgreementAsOriginator(recipient, tid);
115 agreement && !agreement->get().IsReset())
124 uint32_t packets = qosTxop->GetWifiMacQueue()->GetNPackets(queueId);
127 (qosTxop->GetBlockAckThreshold() > 0 && packets >= qosTxop->GetBlockAckThreshold()) ||
130 m_mac->GetVhtConfiguration());
140 uint16_t startingSeq,
153 hdr.
SetAddr1(addr1 ? *addr1 : dest);
185 GetBaManager(tid)->CreateOriginatorAgreement(reqHdr, dest);
187 packet->AddHeader(reqHdr);
188 packet->AddHeader(actionHdr);
193 uint16_t sequence =
m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader());
194 mpdu->GetHeader().SetSequenceNumber(sequence);
199 if (!
TryAddMpdu(mpdu, txParams, availableTime))
201 NS_LOG_DEBUG(
"Not enough time to send the ADDBA Request frame");
206 m_mac->GetQosTxop(tid)->GetWifiMacQueue()->Enqueue(mpdu);
239 auto tid = reqHdr.
GetTid();
242 auto bufferSize = std::min(
m_mac->GetMpduBufferSize(),
m_mac->GetMaxBaBufferSize(originator));
252 packet->AddHeader(respHdr);
253 packet->AddHeader(actionHdr);
258 originator = *originatorMld;
265 auto agreement =
GetBaManager(tid)->GetAgreementAsRecipient(originator, tid);
271 agreement->get().m_inactivityEvent =
296 NS_ASSERT_MSG(it->second,
"The pointer to the pending ADDBA_RESPONSE cannot be null");
307 m_mac->GetQosTxop(tid)->Queue(mpdu);
333 packet->AddHeader(delbaHdr);
334 packet->AddHeader(actionHdr);
345 if (
auto mpdu =
GetBar(edca->GetAccessCategory());
370 uint16_t startingSeq =
377 edca->GetBlockAckInactivityTimeout(),
387 return SendDataFrame(peekedItem, availableTime, initialFrame);
400 std::optional<uint8_t> optTid,
401 std::optional<Mac48Address> optAddress)
403 NS_LOG_FUNCTION(
this << +ac << optTid.has_value() << optAddress.has_value());
405 "Either both or none of TID and address must be provided");
409 auto queue =
m_mac->GetTxopQueue(ac);
410 queue->WipeAllExpiredMpdus();
419 while ((bar = queue->PeekFirstAvailable(
m_linkId, prevBar)) && bar && bar->GetHeader().IsCtl())
421 if (bar->GetHeader().IsBlockAckReq())
424 bar->GetPacket()->PeekHeader(reqHdr);
427 auto recipientMld =
m_mac->GetMldAddress(recipient);
433 (bar->GetHeader().GetAddr2() ==
m_mac->GetAddress() && recipientMld &&
435 "Cannot use link " << +
m_linkId <<
" to send BAR: " << *bar);
443 <<
" cannot be returned because it is not addressed"
444 " to the given station for the given TID");
449 auto agreement =
m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid);
452 NS_LOG_DEBUG(
"BA agreement with " << recipient <<
" for TID=" << +tid
453 <<
" was torn down");
458 if (
auto seqNo = agreement->get().GetStartingSequence();
463 packet->AddHeader(reqHdr);
464 auto updatedBar =
Create<WifiMpdu>(packet, bar->GetHeader(), bar->GetTimestamp());
465 queue->Replace(bar, updatedBar);
475 if (bar->GetHeader().GetAddr2() ==
m_self && recipientMld)
482 while ((otherBar = queue->PeekByQueueId(queueId, otherBar)))
484 if (otherBar->GetHeader().IsBlockAckReq())
487 otherBar->GetPacket()->PeekHeader(otherReqHdr);
490 queue->Remove(otherBar);
498 if (bar->GetHeader().IsTrigger() && !optAddress && !selectedBar)
509 auto baManager =
m_mac->GetQosTxop(ac)->GetBaManager();
510 for (
const auto& [recipient, tid] : baManager->GetSendBarIfDataQueuedList())
512 if (queue->PeekByTidAndAddress(tid, recipient))
514 auto [reqHdr, hdr] =
m_mac->GetQosTxop(ac)->PrepareBlockAckRequest(recipient, tid);
516 pkt->AddHeader(reqHdr);
518 baManager->RemoveFromSendBarIfDataQueuedList(recipient, tid);
519 queue->Enqueue(selectedBar);
525 if (selectedBar && selectedBar->GetHeader().GetAddr2() !=
m_self)
529 NS_ASSERT(selectedBar->GetHeader().GetAddr2() ==
m_mac->GetAddress());
531 const auto currAddr1 = selectedBar->GetHeader().GetAddr1();
534 selectedBar->GetHeader().SetAddr1(addr1);
535 selectedBar->GetHeader().SetAddr2(
m_self);
536 queue->Enqueue(selectedBar);
550 if (!mpdu->GetHeader().IsBlockAckReq())
552 NS_LOG_DEBUG(
"Block Ack Manager returned no frame to send");
564 if (!
TryAddMpdu(mpdu, txParams, availableTime))
566 NS_LOG_DEBUG(
"Not enough time to send the BAR frame returned by the Block Ack Manager");
574 txParams.
m_txVector = blockAcknowledgment->blockAckTxVector;
586 NS_ASSERT(peekedItem && peekedItem->GetHeader().IsQosData() &&
587 !peekedItem->GetHeader().GetAddr1().IsBroadcast() && !peekedItem->IsFragment());
595 edca->GetNextMpdu(
m_linkId, peekedItem, txParams, availableTime, initialFrame);
604 std::vector<Ptr<WifiMpdu>> mpduList =
608 if (mpduList.size() > 1)
636 auto blockAcknowledgment =
static_cast<WifiBlockAck*
>(acknowledgment);
638 blockAcknowledgment->blockAckTxVector,
640 blockAcknowledgment->acknowledgmentTime =
m_phy->
GetSifs() + baTxDuration;
644 auto barBlockAcknowledgment =
static_cast<WifiBarBlockAck*
>(acknowledgment);
647 barBlockAcknowledgment->blockAckReqTxVector,
651 barBlockAcknowledgment->blockAckTxVector,
653 barBlockAcknowledgment->acknowledgmentTime =
679 if (mpdu->GetHeader().IsQosData())
681 uint8_t tid = mpdu->GetHeader().GetQosTid();
684 if (
m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(), tid))
687 edca->GetBaManager()->NotifyGotAck(
m_linkId, mpdu);
690 else if (mpdu->GetHeader().IsAction())
692 auto addr1 = mpdu->GetHeader().GetAddr1();
696 p->RemoveHeader(actionHdr);
702 p->PeekHeader(delBa);
703 auto tid = delBa.
GetTid();
706 GetBaManager(tid)->DestroyOriginatorAgreement(address, tid);
710 GetBaManager(tid)->DestroyRecipientAgreement(address, tid);
717 p->PeekHeader(addBa);
729 p->PeekHeader(addBa);
730 auto tid = addBa.
GetTid();
732 "Recipient BA agreement {" << address <<
", " << +tid
752 NS_LOG_DEBUG(
"Schedule a transmission from Block Ack Manager in a SIFS");
770 if (mpdu->GetHeader().IsQosData())
772 GetBaManager(mpdu->GetHeader().GetQosTid())->NotifyDiscardedMpdu(mpdu);
774 else if (mpdu->GetHeader().IsAction())
777 mpdu->GetPacket()->PeekHeader(actionHdr);
781 uint8_t tid =
GetTid(mpdu->GetPacket(), mpdu->GetHeader());
782 auto recipient = mpdu->GetHeader().GetAddr1();
786 recipient = *mldAddr;
788 if (
auto agreement =
GetBaManager(tid)->GetAgreementAsOriginator(recipient, tid);
789 agreement && agreement->get().IsPending())
793 qosTxop->NotifyOriginatorAgreementNoReply(recipient, tid);
805 if (mpdu->IsQueued())
816 if (mpdu->GetHeader().IsQosData())
818 uint8_t tid = mpdu->GetHeader().GetQosTid();
821 if (
m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(), tid))
824 edca->GetBaManager()->NotifyMissedAck(
m_linkId, mpdu);
836 auto tids = psdu->GetTids();
839 !
m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), *tids.begin()))
846 auto mpduIt = psdu->end();
850 std::advance(mpduIt, -1);
852 const WifiMacHeader& hdr = (*mpduIt)->GetOriginal()->GetHeader();
858 if (!hdr.
IsRetry() && !(*mpduIt)->IsInFlight())
863 uint16_t currentNextSeq =
m_txMiddle->PeekNextSequenceNumberFor(&hdr);
867 (*mpduIt)->UnassignSeqNo();
871 <<
", next sequence "
873 << hdr.
GetAddr1() <<
",tid=" << +tid <<
" is "
874 <<
m_txMiddle->PeekNextSequenceNumberFor(&hdr));
878 }
while (mpduIt != psdu->begin());
910#ifdef NS3_BUILD_PROFILE_DEBUG
917 NS_ASSERT(mpdu->GetHeader().IsCtl() || mpdu->IsQueued());
936 if (mpdu->IsQueued())
991 NS_ASSERT_MSG(tids.size() <= 1,
"Multi-TID A-MPDUs are not supported");
1028 "Acknowledgment method incompatible with a Multi-TID A-MPDU");
1029 uint8_t tid = *tids.begin();
1032 auto [reqHdr, hdr] = edca->PrepareBlockAckRequest(
m_psdu->
GetAddr1(), tid);
1039 NS_ABORT_MSG(
"Unable to handle the selected acknowledgment method ("
1067 auto& hdr = mpdu->GetHeader();
1069 if (hdr.IsQosData() && hdr.HasData())
1071 auto tid = hdr.GetQosTid();
1072 m_mac->GetQosTxop(tid)->CompleteMpduTx(mpdu);
1083 std::array<std::optional<uint8_t>, 8> queueSizeForTid;
1092 auto edca =
m_mac->GetQosTxop(tid);
1097 if (!queueSizeForTid[tid].has_value())
1099 queueSizeForTid[tid] =
1100 edca->GetQosQueueSize(tid, mpdu->GetOriginal()->GetHeader().GetAddr1());
1128 NS_LOG_DEBUG(
"Transmitting a PSDU: " << *psdu <<
" TXVECTOR: " << txVector);
1133 if (psdu->IsAggregate())
1144 Time ppduDurationLimit)
const
1159 if (mpdu->GetHeader().IsQosData())
1161 tid = mpdu->GetHeader().GetQosTid();
1169 NS_ABORT_MSG(
"Cannot aggregate a non-QoS data frame to an A-MPDU that does"
1170 " not contain any QoS data frame");
1194 if (maxAmpduSize == 0)
1200 if (ampduSize > maxAmpduSize)
1202 NS_LOG_DEBUG(
"the frame does not meet the constraint on max A-MPDU size (" << maxAmpduSize
1212 Time availableTime)
const
1214 NS_ASSERT(msdu && msdu->GetHeader().IsQosData());
1224 auto protectionTime = txParams.
m_protection->protectionTime;
1226 std::unique_ptr<WifiProtection> protection;
1228 bool protectionSwapped =
false;
1234 protectionTime = protection->protectionTime;
1238 protectionSwapped =
true;
1246 std::unique_ptr<WifiAcknowledgment> acknowledgment;
1247 acknowledgment =
GetAckManager()->TryAggregateMsdu(msdu, txParams);
1248 bool acknowledgmentSwapped =
false;
1254 acknowledgmentTime = acknowledgment->acknowledgmentTime;
1258 acknowledgmentSwapped =
true;
1260 NS_ASSERT(acknowledgmentTime.has_value());
1265 ppduDurationLimit = availableTime - *protectionTime - *acknowledgmentTime;
1274 if (protectionSwapped)
1278 if (acknowledgmentSwapped)
1291 Time ppduDurationLimit)
const
1293 NS_ASSERT(msdu && msdu->GetHeader().IsQosData());
1296 auto receiver = msdu->GetHeader().GetAddr1();
1297 auto tid = msdu->GetHeader().GetQosTid();
1300 NS_ASSERT_MSG(psduInfo,
"No PSDU info for receiver " << receiver);
1303 uint16_t maxAmsduSize =
m_msduAggregator->GetMaxAmsduSize(receiver, tid, modulation);
1305 if (maxAmsduSize == 0)
1311 if (psduInfo->amsduSize > maxAmsduSize)
1313 NS_LOG_DEBUG(
"No other MSDU can be aggregated: maximum A-MSDU size (" << maxAmsduSize
1320 auto ampduSize = txParams.
GetSize(receiver);
1367 auto recipient = psdu->GetAddr1();
1372 if (psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsBlockAckReq())
1376 psdu->GetPayload(0)->PeekHeader(baReqHdr);
1382 std::set<uint8_t> tids = psdu->GetTids();
1383 NS_ABORT_MSG_IF(tids.size() > 1,
"Multi-TID A-MPDUs not handled here");
1385 tid = *tids.begin();
1390 if (edca->UseExplicitBarAfterMissedBlockAck() || isBar)
1393 if (
GetBaManager(tid)->NeedBarRetransmission(tid, recipientMld))
1395 NS_LOG_DEBUG(
"Missed Block Ack, transmit a BlockAckReq");
1408 psdu->GetHeader(0).SetRetry();
1413 auto [reqHdr, hdr] = edca->PrepareBlockAckRequest(recipient, tid);
1420 NS_LOG_DEBUG(
"Missed Block Ack, do not transmit a BlockAckReq");
1428 if (
m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid))
1432 GetBaManager(tid)->AddToSendBarIfDataQueuedList(recipientMld, tid);
1441 ->ReportAmpduTxStatus(recipient, 0, psdu->GetNMpdus(), 0, 0, txVector);
1444 NS_LOG_DEBUG(
"Missed Block Ack, do not retransmit the data frames");
1455 NS_LOG_DEBUG(
"Missed Block Ack, retransmit data frames");
1472 auto addr1 = agreement.
GetPeer();
1475 addr1 = *originator;
1488 packet->AddHeader(blockAck);
1504 psdu->GetHeader(0).SetDuration(baDurationId);
1508 psdu->GetPayload(0)->AddPacketTag(tag);
1520 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() ==
m_self);
1522 double rxSnr = rxSignalInfo.
snr;
1537 mpdu->GetPacket()->PeekPacketTag(tag);
1557 mpdu->GetPacket()->PeekPacketTag(tag);
1561 mpdu->GetPacket()->PeekHeader(blockAck);
1563 std::pair<uint16_t, uint16_t> ret =
1566 m_mac->GetMldAddress(sender).value_or(sender),
1599 mpdu->GetPacket()->PeekHeader(blockAckReq);
1603 auto agreement =
m_mac->GetBaAgreementEstablishedAsRecipient(sender, tid);
1607 NS_LOG_DEBUG(
"There's not a valid agreement for this BlockAckReq");
1612 m_mac->GetMldAddress(sender).value_or(sender),
1638 if (
m_mac->GetBaAgreementEstablishedAsRecipient(hdr.
GetAddr2(), tid))
1674 NS_ASSERT(mpdu->GetHeader().IsAction());
1675 const auto from = mpdu->GetOriginal()->GetHeader().GetAddr2();
1678 auto packet = mpdu->GetPacket()->Copy();
1679 packet->RemoveHeader(actionHdr);
1682 const auto ackTxVector =
1684 const auto ackTxTime =
1695 packet->RemoveHeader(reqHdr);
1710 packet->RemoveHeader(respHdr);
1716 const auto recipient =
1717 GetWifiRemoteStationManager()->GetMldAddress(from).value_or(from);
1718 m_mac->GetQosTxop(respHdr.GetTid())->GotAddBaResponse(respHdr, recipient);
1719 GetBaManager(respHdr.GetTid())
1720 ->SetBlockAckInactivityCallback(
1721 MakeCallback(&HtFrameExchangeManager::SendDelbaFrame, this));
1728 packet->RemoveHeader(delBaHdr);
1738 ->DestroyRecipientAgreement(recipient, delBaHdr.
GetTid());
1745 m_mac->GetQosTxop(delBaHdr.
GetTid())->GotDelBaFrame(&delBaHdr, recipient);
1751 NS_FATAL_ERROR(
"Unsupported Action field in Block Ack Action frame");
1763 const std::vector<bool>& perMpduStatus)
1765 std::set<uint8_t> tids = psdu->GetTids();
1768 if (tids.size() == 1)
1770 uint8_t tid = *tids.begin();
1778 auto agreement =
m_mac->GetBaAgreementEstablishedAsRecipient(psdu->GetAddr2(), tid);
1786 psdu->GetDuration(),
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)
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
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 upon successful protection mechanism.
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.
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
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...
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
HtFrameExchangeManager handles the frame exchange sequences for HT stations.
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)
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
Sends DELBA frame to cancel a block ack agreement with STA addressed by addr for TID tid.
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 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.
void ProtectionCompleted() override
Transmit prepared frame upon successful protection mechanism.
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...
bool SendAddBaRequest(Mac48Address recipient, uint8_t tid, uint16_t startingSeq, uint16_t timeout, bool immediateBAck, Time availableTime)
Sends an ADDBA Request to establish a block ack agreement with STA addressed by recipient for TID tid...
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 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
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...
virtual void MissedBlockAck(Ptr< WifiPsdu > psdu, const WifiTxVector &txVector, bool &resetCw)
Take necessary actions when a BlockAck is missed, such as scheduling a BlockAckReq frame or the retra...
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef (MAC address and TID)
void SendBlockAck(const RecipientBlockAckAgreement &agreement, Time durationId, WifiTxVector &blockAckTxVector, double rxSnr)
Create a BlockAck frame with header equal to blockAck and start its transmission.
Smart pointer class similar to boost::intrusive_ptr.
QosFrameExchangeManager handles the frame exchange sequences for QoS stations.
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)
void TransmissionFailed() override
Take necessary actions upon a transmission failure.
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.
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...
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...
void DoDispose() override
Destructor implementation.
AcIndex GetAccessCategory() const
Get the access category of this object.
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
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)
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.
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.
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.
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.
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
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.
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.
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.
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.
bool IsRunning() const
Return true if the timer is running.
void Cancel()
Cancel the timer.
void Set(Reason reason, const Time &delay, const std::set< Mac48Address > &from, MEM mem_ptr, OBJ obj, Args... args)
This method is called when a frame soliciting a response is transmitted.
Reason GetReason() const
Get the reason why the timer was started.
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.
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.
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).
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