A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
frame-exchange-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "snr-tag.h"
12#include "sta-wifi-mac.h"
13#include "wifi-mac-queue.h"
14#include "wifi-mac-trailer.h"
15#include "wifi-utils.h"
16
17#include "ns3/abort.h"
18#include "ns3/log.h"
19
20#undef NS_LOG_APPEND_CONTEXT
21#define NS_LOG_APPEND_CONTEXT WIFI_FEM_NS_LOG_APPEND_CONTEXT
22
23// Time (in nanoseconds) to be added to the PSDU duration to yield the duration
24// of the timer that is started when the PHY indicates the start of the reception
25// of a frame and we are waiting for a response.
26#define PSDU_DURATION_SAFEGUARD 400
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("FrameExchangeManager");
32
33NS_OBJECT_ENSURE_REGISTERED(FrameExchangeManager);
34
35TypeId
37{
38 static TypeId tid = TypeId("ns3::FrameExchangeManager")
40 .AddConstructor<FrameExchangeManager>()
41 .SetGroupName("Wifi");
42 return tid;
43}
44
46 : m_navEnd(Seconds(0)),
47 m_linkId(0),
48 m_allowedWidth(0),
49 m_promisc(false),
50 m_moreFragments(false)
51{
52 NS_LOG_FUNCTION(this);
53}
54
59
60void
76
77void
79{
80 NS_LOG_FUNCTION(this);
81 Reset();
82 m_fragmentedPacket = nullptr;
83 m_mac = nullptr;
84 m_txMiddle = nullptr;
85 m_rxMiddle = nullptr;
86 m_channelAccessManager = nullptr;
87 m_protectionManager = nullptr;
88 m_ackManager = nullptr;
89 ResetPhy();
91}
92
93void
95{
96 NS_LOG_FUNCTION(this << protectionManager);
97 m_protectionManager = protectionManager;
98}
99
105
106void
108{
109 NS_LOG_FUNCTION(this << ackManager);
110 m_ackManager = ackManager;
111}
112
118
119void
121{
122 NS_LOG_FUNCTION(this << +linkId);
123 m_linkId = linkId;
124}
125
126void
128{
129 NS_LOG_FUNCTION(this << mac);
130 m_mac = mac;
131}
132
133void
135{
136 NS_LOG_FUNCTION(this << txMiddle);
137 m_txMiddle = txMiddle;
138}
139
140void
142{
143 NS_LOG_FUNCTION(this << rxMiddle);
144 m_rxMiddle = rxMiddle;
145}
146
147void
149{
150 NS_LOG_FUNCTION(this << channelAccessManager);
151 m_channelAccessManager = channelAccessManager;
152}
153
156{
157 return m_mac->GetWifiRemoteStationManager(m_linkId);
158}
159
160void
172
173void
175{
176 NS_LOG_FUNCTION(this);
177 if (m_phy)
178 {
180 "PhyRxPayloadBegin",
183 "PhyRxMacHeaderEnd",
185 if (m_phy->GetState())
186 {
191 std::vector<bool>>());
193 }
194 m_phy = nullptr;
195 m_ongoingRxInfo.macHdr.reset();
197 }
198}
199
200void
202{
203 NS_LOG_FUNCTION(this << address);
204 // For APs, the BSSID is the MAC address. For STAs, the BSSID will be overwritten
205 // when receiving Beacon frames or Probe Response frames
206 SetBssid(address);
207 m_self = address;
208}
209
212{
213 return m_self;
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << bssid);
220 m_bssid = bssid;
221}
222
225{
226 return m_bssid;
227}
228
229MHz_u
234
235void
237{
238 NS_LOG_FUNCTION(this << &callback);
239 m_droppedMpduCallback = callback;
240}
241
242void
244{
245 NS_LOG_FUNCTION(this << &callback);
246 m_ackedMpduCallback = callback;
247}
248
249void
254
255bool
257{
258 return m_promisc;
259}
260
261const WifiTxTimer&
266
267void
273
274void
276{
277 NS_LOG_FUNCTION(this << "PSDU reception started for " << psduDuration.As(Time::US)
278 << " (txVector: " << txVector << ")");
279
281 "The TX timer and the NAV reset event cannot be both running");
282
283 // No need to reschedule timeouts if PSDU duration is null. In this case,
284 // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered)
285 // and CCA will take over
286 if (m_txTimer.IsRunning() && psduDuration.IsStrictlyPositive())
287 {
288 // we are waiting for a response and something arrived
289 NS_LOG_DEBUG("Rescheduling timeout event");
291 // PHY has switched to RX, so we can reset the ack timeout
292 m_channelAccessManager->NotifyAckTimeoutResetNow();
293 }
294
296 {
298 }
299
300 m_ongoingRxInfo = {std::nullopt, txVector, Simulator::Now() + psduDuration};
301}
302
303void
305 const WifiTxVector& txVector,
306 Time psduDuration)
307{
308 NS_LOG_FUNCTION(this << macHdr << txVector << psduDuration.As(Time::MS));
309 m_ongoingRxInfo = {macHdr, txVector, Simulator::Now() + psduDuration};
310}
311
312std::optional<std::reference_wrapper<const FrameExchangeManager::OngoingRxInfo>>
314{
316 {
317 return m_ongoingRxInfo;
318 }
319 return std::nullopt;
320}
321
322std::optional<std::reference_wrapper<const WifiMacHeader>>
324{
325 if (auto info = GetOngoingRxInfo(); info.has_value() && info->get().macHdr.has_value())
326 {
327 return info->get().macHdr.value();
328 }
329 return std::nullopt;
330}
331
332bool
334{
335 NS_LOG_FUNCTION(this << dcf << allowedWidth);
336
338 if (m_txTimer.IsRunning())
339 {
341 }
342 m_dcf = dcf;
343 m_allowedWidth = allowedWidth;
344
345 Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue();
346
347 // Even though channel access is requested when the queue is not empty, at
348 // the time channel access is granted the lifetime of the packet might be
349 // expired and the queue might be empty.
350 queue->WipeAllExpiredMpdus();
351
352 Ptr<WifiMpdu> mpdu = queue->Peek(m_linkId);
353
354 if (!mpdu)
355 {
356 NS_LOG_DEBUG("Queue empty");
358 m_dcf = nullptr;
359 return false;
360 }
361
363
364 NS_ASSERT(mpdu->GetHeader().IsData() || mpdu->GetHeader().IsMgt());
365
366 // assign a sequence number if this is not a fragment nor a retransmission
367 if (!mpdu->IsFragment() && !mpdu->GetHeader().IsRetry())
368 {
369 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader());
370 mpdu->AssignSeqNo(sequence);
371 }
372
373 NS_LOG_DEBUG("MPDU payload size=" << mpdu->GetPacketSize()
374 << ", to=" << mpdu->GetHeader().GetAddr1()
375 << ", seq=" << mpdu->GetHeader().GetSequenceControl());
376
377 // check if the MSDU needs to be fragmented
378 mpdu = GetFirstFragmentIfNeeded(mpdu);
379
382 WifiTxParameters txParams;
383 txParams.m_txVector =
384 GetWifiRemoteStationManager()->GetDataTxVector(mpdu->GetHeader(), m_allowedWidth);
385 txParams.AddMpdu(mpdu);
386 UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
387 txParams.m_protection = m_protectionManager->TryAddMpdu(mpdu, txParams);
388 txParams.m_acknowledgment = m_ackManager->TryAddMpdu(mpdu, txParams);
389
390 SendMpduWithProtection(mpdu, txParams);
391
392 return true;
393}
394
397{
398 NS_LOG_FUNCTION(this << *mpdu);
399
400 if (mpdu->IsFragment())
401 {
402 // a fragment cannot be further fragmented
404 }
405 else if (GetWifiRemoteStationManager()->NeedFragmentation(mpdu))
406 {
407 NS_LOG_DEBUG("Fragmenting the MSDU");
408 m_fragmentedPacket = mpdu->GetPacket()->Copy();
409 // create the first fragment
411 0,
412 GetWifiRemoteStationManager()->GetFragmentSize(mpdu, 0));
413 // enqueue the first fragment
414 Ptr<WifiMpdu> item = Create<WifiMpdu>(fragment, mpdu->GetHeader());
415 item->GetHeader().SetMoreFragments();
416 m_mac->GetTxopQueue(mpdu->GetQueueAc())->Replace(mpdu, item);
417 return item;
418 }
419 return mpdu;
420}
421
422void
424{
425 NS_LOG_FUNCTION(this << *mpdu << &txParams);
426
427 m_mpdu = mpdu;
428 m_txParams = std::move(txParams);
429
430 // If protection is required, the MPDU must be stored in some queue because
431 // it is not put back in a queue if the RTS/CTS exchange fails
433 m_mpdu->GetHeader().IsCtl() || m_mpdu->IsQueued());
434
435 // Make sure that the acknowledgment time has been computed, so that SendRts()
436 // and SendCtsToSelf() can reuse this value.
438
439 if (!m_txParams.m_acknowledgment->acknowledgmentTime.has_value())
440 {
442 }
443
444 // Set QoS Ack policy if this is a QoS data frame
446
447 if (m_mpdu->IsQueued())
448 {
449 m_mpdu->SetInFlight(m_linkId);
450 }
451
453}
454
455void
457{
458 NS_LOG_FUNCTION(this << &txParams);
459
460 switch (txParams.m_protection->method)
461 {
463 SendRts(txParams);
464 break;
466 SendCtsToSelf(txParams);
467 break;
470 break;
471 default:
472 NS_ABORT_MSG("Unknown protection type: " << txParams.m_protection.get());
473 }
474}
475
476void
485
486const std::set<Mac48Address>&
491
492void
494{
495 NS_LOG_FUNCTION(this);
496
499 m_phy->GetPhyBand());
500
502
504 {
505 if (!m_mpdu->GetHeader().IsQosData() ||
506 m_mpdu->GetHeader().GetQosAckPolicy() == WifiMacHeader::NO_ACK)
507 {
508 // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
510 }
511
512 Simulator::Schedule(txDuration, [=, this]() {
514 m_mpdu = nullptr;
515 });
516 }
518 {
519 m_mpdu->GetHeader().SetDuration(
520 GetFrameDurationId(m_mpdu->GetHeader(),
524
525 // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
526 // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
527 // aRxPHYStartDelay equals the time to transmit the PHY header.
528 auto normalAcknowledgment = static_cast<WifiNormalAck*>(m_txParams.m_acknowledgment.get());
529
530 Time timeout =
531 txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
532 m_phy->CalculatePhyPreambleAndHeaderDuration(normalAcknowledgment->ackTxVector);
535 timeout,
536 {m_mpdu->GetHeader().GetAddr1()},
538 this,
539 m_mpdu,
541 m_channelAccessManager->NotifyAckTimeoutStartNow(timeout);
542 }
543 else
544 {
545 NS_ABORT_MSG("Unable to handle the selected acknowledgment method ("
546 << m_txParams.m_acknowledgment.get() << ")");
547 }
548
549 // transmit the MPDU
551}
552
553void
555{
556 NS_LOG_FUNCTION(this << *mpdu << txVector);
557
558 auto psdu = Create<WifiPsdu>(mpdu, false);
559 FinalizeMacHeader(psdu);
560 m_allowedWidth = std::min(m_allowedWidth, txVector.GetChannelWidth());
561 m_phy->Send(psdu, txVector);
562}
563
564void
566{
567 NS_LOG_FUNCTION(this << psdu);
568
569 if (m_mac->GetTypeOfStation() != STA)
570 {
571 return;
572 }
573
574 auto pmMode = StaticCast<StaWifiMac>(m_mac)->GetPmMode(m_linkId);
575
576 for (const auto& mpdu : *PeekPointer(psdu))
577 {
578 switch (pmMode)
579 {
580 case WIFI_PM_ACTIVE:
582 mpdu->GetHeader().SetNoPowerManagement();
583 break;
586 mpdu->GetHeader().SetPowerManagement();
587 break;
588 default:
589 NS_ABORT_MSG("Unknown PM mode: " << +pmMode);
590 }
591 }
592}
593
594void
596{
597 NS_LOG_DEBUG(this << *mpdu);
598
599 if (mpdu->IsQueued())
600 {
601 m_mac->GetTxopQueue(mpdu->GetQueueAc())->DequeueIfQueued({mpdu});
602 }
603}
604
607{
608 return mpdu->GetSize();
609}
610
611void
613{
614 NS_LOG_FUNCTION(this << protection);
615 NS_ASSERT(protection);
616
617 if (protection->method == WifiProtection::NONE)
618 {
619 protection->protectionTime = Seconds(0);
620 }
621 else if (protection->method == WifiProtection::RTS_CTS)
622 {
623 auto rtsCtsProtection = static_cast<WifiRtsCtsProtection*>(protection);
624 rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration(GetRtsSize(),
625 rtsCtsProtection->rtsTxVector,
626 m_phy->GetPhyBand()) +
628 rtsCtsProtection->ctsTxVector,
629 m_phy->GetPhyBand()) +
630 2 * m_phy->GetSifs();
631 }
632 else if (protection->method == WifiProtection::CTS_TO_SELF)
633 {
634 auto ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*>(protection);
635 ctsToSelfProtection->protectionTime =
637 ctsToSelfProtection->ctsTxVector,
638 m_phy->GetPhyBand()) +
639 m_phy->GetSifs();
640 }
641}
642
643void
645{
646 NS_LOG_FUNCTION(this << acknowledgment);
647 NS_ASSERT(acknowledgment);
648
649 if (acknowledgment->method == WifiAcknowledgment::NONE)
650 {
651 acknowledgment->acknowledgmentTime = Seconds(0);
652 }
653 else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
654 {
655 auto normalAcknowledgment = static_cast<WifiNormalAck*>(acknowledgment);
656 normalAcknowledgment->acknowledgmentTime =
658 normalAcknowledgment->ackTxVector,
659 m_phy->GetPhyBand());
660 }
661}
662
663Time
665 Mac48Address receiver,
666 const WifiTxParameters& txParams) const
667{
668 return m_phy->CalculateTxDuration(ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand());
669}
670
671void
673{
674 txParams.m_txDuration = GetTxDuration(txParams.GetSize(receiver), receiver, txParams);
675}
676
677Time
679 uint32_t size,
680 const WifiTxParameters& txParams,
681 Ptr<Packet> fragmentedPacket) const
682{
683 NS_LOG_FUNCTION(this << header << size << &txParams << fragmentedPacket);
684
685 NS_ASSERT(txParams.m_acknowledgment &&
686 txParams.m_acknowledgment->acknowledgmentTime.has_value());
687 auto durationId = *txParams.m_acknowledgment->acknowledgmentTime;
688
689 // if the current frame is a fragment followed by another fragment, we have to
690 // update the Duration/ID to cover the next fragment and the corresponding Ack
691 if (header.IsMoreFragments())
692 {
693 uint32_t payloadSize = size - header.GetSize() - WIFI_MAC_FCS_LENGTH;
694 uint32_t nextFragmentOffset = (header.GetFragmentNumber() + 1) * payloadSize;
695 uint32_t nextFragmentSize =
696 std::min(fragmentedPacket->GetSize() - nextFragmentOffset, payloadSize);
697 WifiTxVector ackTxVector =
698 GetWifiRemoteStationManager()->GetAckTxVector(header.GetAddr1(), txParams.m_txVector);
699
700 durationId +=
701 2 * m_phy->GetSifs() +
703 m_phy->CalculateTxDuration(nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand());
704 }
705 return durationId;
706}
707
708Time
710 Time txDuration,
711 Time response) const
712{
713 NS_LOG_FUNCTION(this << rtsTxVector << txDuration << response);
714
715 WifiTxVector ctsTxVector;
716 ctsTxVector = GetWifiRemoteStationManager()->GetCtsTxVector(m_self, rtsTxVector.GetMode());
717
718 return m_phy->GetSifs() +
719 m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()) /* CTS */
720 + m_phy->GetSifs() + txDuration + response;
721}
722
723void
725{
726 NS_LOG_FUNCTION(this << &txParams);
727
728 NS_ASSERT(txParams.GetPsduInfoMap().size() == 1);
729 Mac48Address receiver = txParams.GetPsduInfoMap().begin()->first;
730
731 WifiMacHeader rts;
733 rts.SetDsNotFrom();
734 rts.SetDsNotTo();
735 rts.SetNoRetry();
736 rts.SetNoMoreFragments();
737 rts.SetAddr1(receiver);
738 rts.SetAddr2(m_self);
739
740 NS_ASSERT(txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
741 auto rtsCtsProtection = static_cast<WifiRtsCtsProtection*>(txParams.m_protection.get());
742
743 NS_ASSERT(txParams.m_txDuration.has_value());
744 NS_ASSERT(txParams.m_acknowledgment->acknowledgmentTime.has_value());
745 rts.SetDuration(GetRtsDurationId(rtsCtsProtection->rtsTxVector,
746 *txParams.m_txDuration,
747 *txParams.m_acknowledgment->acknowledgmentTime));
749
750 // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
751 // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
752 // aRxPHYStartDelay equals the time to transmit the PHY header.
754 rtsCtsProtection->rtsTxVector,
755 m_phy->GetPhyBand()) +
756 m_phy->GetSifs() + m_phy->GetSlot() +
757 m_phy->CalculatePhyPreambleAndHeaderDuration(rtsCtsProtection->ctsTxVector);
760 timeout,
761 {receiver},
763 this,
764 mpdu,
765 rtsCtsProtection->rtsTxVector);
766 m_channelAccessManager->NotifyCtsTimeoutStartNow(timeout);
767 NS_ASSERT(m_sentRtsTo.empty());
768 m_sentRtsTo = {receiver};
769
770 ForwardMpduDown(mpdu, rtsCtsProtection->rtsTxVector);
771}
772
773void
775 WifiTxVector& ctsTxVector,
776 double rtsSnr)
777{
778 NS_LOG_FUNCTION(this << rtsHdr << ctsTxVector << rtsSnr);
779
780 WifiMacHeader cts;
782 cts.SetDsNotFrom();
783 cts.SetDsNotTo();
784 cts.SetNoMoreFragments();
785 cts.SetNoRetry();
786 cts.SetAddr1(rtsHdr.GetAddr2());
787 Time duration = rtsHdr.GetDuration() - m_phy->GetSifs() -
789 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
790 if (duration.IsStrictlyNegative())
791 {
792 duration = Seconds(0);
793 }
794 cts.SetDuration(duration);
795
796 Ptr<Packet> packet = Create<Packet>();
797
798 SnrTag tag;
799 tag.Set(rtsSnr);
800 packet->AddPacketTag(tag);
801
802 // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
803 ForwardMpduDown(Create<WifiMpdu>(packet, cts), ctsTxVector);
804}
805
806void
808 WifiMode rtsTxMode,
809 double rtsSnr)
810{
811 NS_LOG_FUNCTION(this << rtsHdr << rtsTxMode << rtsSnr);
812
813 WifiTxVector ctsTxVector =
814 GetWifiRemoteStationManager()->GetCtsTxVector(rtsHdr.GetAddr2(), rtsTxMode);
815 DoSendCtsAfterRts(rtsHdr, ctsTxVector, rtsSnr);
816}
817
818Time
820 Time txDuration,
821 Time response) const
822{
823 NS_LOG_FUNCTION(this << ctsTxVector << txDuration << response);
824
825 return m_phy->GetSifs() + txDuration + response;
826}
827
828void
830{
831 NS_LOG_FUNCTION(this << &txParams);
832
833 WifiMacHeader cts;
835 cts.SetDsNotFrom();
836 cts.SetDsNotTo();
837 cts.SetNoMoreFragments();
838 cts.SetNoRetry();
839 cts.SetAddr1(m_self);
840
841 NS_ASSERT(txParams.m_protection &&
842 txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
843 auto ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*>(txParams.m_protection.get());
844
845 NS_ASSERT(txParams.m_txDuration.has_value());
846 NS_ASSERT(txParams.m_acknowledgment->acknowledgmentTime.has_value());
847 cts.SetDuration(GetCtsToSelfDurationId(ctsToSelfProtection->ctsTxVector,
848 *txParams.m_txDuration,
849 *txParams.m_acknowledgment->acknowledgmentTime));
850
851 ForwardMpduDown(Create<WifiMpdu>(Create<Packet>(), cts), ctsToSelfProtection->ctsTxVector);
852
853 Time ctsDuration = m_phy->CalculateTxDuration(GetCtsSize(),
854 ctsToSelfProtection->ctsTxVector,
855 m_phy->GetPhyBand());
856 Simulator::Schedule(ctsDuration + m_phy->GetSifs(),
858 this);
859}
860
861void
863 const WifiTxVector& dataTxVector,
864 double dataSnr)
865{
866 NS_LOG_FUNCTION(this << hdr << dataTxVector << dataSnr);
867
868 WifiTxVector ackTxVector =
869 GetWifiRemoteStationManager()->GetAckTxVector(hdr.GetAddr2(), dataTxVector);
870 WifiMacHeader ack;
872 ack.SetDsNotFrom();
873 ack.SetDsNotTo();
874 ack.SetNoRetry();
875 ack.SetNoMoreFragments();
876 ack.SetAddr1(hdr.GetAddr2());
877 // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
878 // minus the time to transmit the Ack frame and its SIFS interval
879 Time duration = hdr.GetDuration() - m_phy->GetSifs() -
881 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
882 if (duration.IsStrictlyNegative())
883 {
884 duration = Seconds(0);
885 }
886 ack.SetDuration(duration);
887
888 Ptr<Packet> packet = Create<Packet>();
889
890 SnrTag tag;
891 tag.Set(dataSnr);
892 packet->AddPacketTag(tag);
893
894 ForwardMpduDown(Create<WifiMpdu>(packet, ack), ackTxVector);
895}
896
899{
900 NS_LOG_FUNCTION(this);
901 NS_ASSERT(m_mpdu->GetHeader().IsMoreFragments());
902
903 WifiMacHeader& hdr = m_mpdu->GetHeader();
905
906 uint32_t startOffset = hdr.GetFragmentNumber() * m_mpdu->GetPacketSize();
907 uint32_t size = m_fragmentedPacket->GetSize() - startOffset;
908
909 if (size > m_mpdu->GetPacketSize())
910 {
911 // this is not the last fragment
912 size = m_mpdu->GetPacketSize();
913 hdr.SetMoreFragments();
914 }
915 else
916 {
917 hdr.SetNoMoreFragments();
918 }
919
920 return Create<WifiMpdu>(m_fragmentedPacket->CreateFragment(startOffset, size), hdr);
921}
922
923void
925{
926 NS_LOG_FUNCTION(this);
927
928 // Upon a transmission success, a non-QoS station transmits the next fragment,
929 // if any, or releases the channel, otherwise
930 if (m_moreFragments)
931 {
932 NS_LOG_DEBUG("Schedule transmission of next fragment in a SIFS");
935 this,
936 m_dcf,
938 m_moreFragments = false;
939 }
940 else
941 {
943 m_dcf = nullptr;
944 }
945}
946
947void
949{
950 NS_LOG_FUNCTION(this);
951 // A non-QoS station always releases the channel upon a transmission failure
953 m_dcf = nullptr;
954}
955
956void
958{
959 NS_LOG_FUNCTION(this << txop);
960 txop->NotifyChannelReleased(m_linkId);
961 m_protectedStas.clear();
962}
963
964void
966{
967 NS_LOG_FUNCTION(this << *mpdu << txVector);
968
969 GetWifiRemoteStationManager()->ReportDataFailed(mpdu);
970
971 if (!GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
972 {
973 NS_LOG_DEBUG("Missed Ack, discard MPDU");
975 // Dequeue the MPDU if it is stored in a queue
976 DequeueMpdu(mpdu);
977 GetWifiRemoteStationManager()->ReportFinalDataFailed(mpdu);
979 }
980 else
981 {
982 NS_LOG_DEBUG("Missed Ack, retransmit MPDU");
983 if (mpdu->IsQueued()) // the MPDU may have been removed due to lifetime expiration
984 {
985 mpdu = m_mac->GetTxopQueue(mpdu->GetQueueAc())->GetOriginal(mpdu);
986 mpdu->ResetInFlight(m_linkId);
987 }
988 mpdu->GetHeader().SetRetry();
991 }
992
993 m_mpdu = nullptr;
995}
996
997void
1002
1003void
1005{
1006 NS_LOG_FUNCTION(this << *rts << txVector);
1007
1009 m_mpdu = nullptr;
1010}
1011
1012void
1014{
1015 NS_LOG_FUNCTION(this << *psdu);
1016
1017 m_sentRtsTo.clear();
1018 for (const auto& mpdu : *PeekPointer(psdu))
1019 {
1020 if (mpdu->IsQueued())
1021 {
1022 mpdu->ResetInFlight(m_linkId);
1023 }
1024 }
1025
1026 GetWifiRemoteStationManager()->ReportRtsFailed(psdu->GetHeader(0));
1027
1028 if (!GetWifiRemoteStationManager()->NeedRetransmission(*psdu->begin()))
1029 {
1030 NS_LOG_DEBUG("Missed CTS, discard MPDU(s)");
1031 GetWifiRemoteStationManager()->ReportFinalRtsFailed(psdu->GetHeader(0));
1032 for (const auto& mpdu : *PeekPointer(psdu))
1033 {
1034 // Dequeue the MPDU if it is stored in a queue
1035 DequeueMpdu(mpdu);
1037 }
1039 }
1040 else
1041 {
1042 NS_LOG_DEBUG("Missed CTS, retransmit MPDU(s)");
1044 }
1045 // Make the sequence numbers of the MPDUs available again if the MPDUs have never
1046 // been transmitted, both in case the MPDUs have been discarded and in case the
1047 // MPDUs have to be transmitted (because a new sequence number is assigned to
1048 // MPDUs that have never been transmitted and are selected for transmission)
1050
1052}
1053
1054void
1056{
1057 NS_LOG_FUNCTION(this << *psdu);
1058
1059 NS_ASSERT_MSG(psdu->GetNMpdus() == 1, "A-MPDUs should be handled by the HT FEM override");
1060 auto mpdu = *psdu->begin();
1061
1062 // the MPDU should be still in the DCF queue, unless it expired.
1063 // If the MPDU has never been transmitted and is not in-flight, it will be assigned
1064 // a sequence number again the next time we try to transmit it. Therefore, we need to
1065 // make its sequence number available again
1066 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
1067 {
1068 mpdu->UnassignSeqNo();
1069 m_txMiddle->SetSequenceNumberFor(&mpdu->GetOriginal()->GetHeader());
1070 }
1071}
1072
1073void
1075{
1076 NS_LOG_FUNCTION(this);
1077
1078 // For internal collisions occurring with the EDCA access method, the appropriate
1079 // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
1080 // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
1081 // (Sec. 10.22.2.11.1 of 802.11-2016).
1082 // We do not prepare the PSDU that the AC losing the internal collision would have
1083 // sent. As an approximation, we consider the frame peeked from the queues of the AC.
1084 Ptr<QosTxop> qosTxop = (txop->IsQosTxop() ? StaticCast<QosTxop>(txop) : nullptr);
1085
1086 auto mpdu =
1087 (qosTxop ? qosTxop->PeekNextMpdu(m_linkId) : txop->GetWifiMacQueue()->Peek(m_linkId));
1088
1089 if (mpdu)
1090 {
1091 if (mpdu->GetHeader().HasData() && !mpdu->GetHeader().GetAddr1().IsGroup())
1092 {
1093 GetWifiRemoteStationManager()->ReportDataFailed(mpdu);
1094 }
1095
1096 if (!mpdu->GetHeader().GetAddr1().IsGroup() &&
1097 !GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
1098 {
1099 NS_LOG_DEBUG("reset DCF");
1100 GetWifiRemoteStationManager()->ReportFinalDataFailed(mpdu);
1101 DequeueMpdu(mpdu);
1103 txop->ResetCw(m_linkId);
1104 }
1105 else
1106 {
1107 NS_LOG_DEBUG("Update CW");
1108 txop->UpdateFailedCw(m_linkId);
1109 }
1110 }
1111
1112 txop->Txop::NotifyChannelReleased(m_linkId);
1113}
1114
1115void
1117{
1118 NS_LOG_DEBUG("Switching channel. Cancelling MAC pending events");
1120 if (m_txTimer.IsRunning())
1121 {
1122 // we were transmitting something before channel switching. Since we will
1123 // not be able to receive the response, have the timer expire now, so that
1124 // we perform the actions required in case of missing response
1126 }
1128}
1129
1130void
1132{
1133 NS_LOG_DEBUG("Device in sleep mode. Cancelling MAC pending events");
1134 Reset();
1135}
1136
1137void
1139{
1140 NS_LOG_DEBUG("Device is switched off. Cancelling MAC pending events");
1141 Reset();
1142}
1143
1144void
1149
1150void
1152 RxSignalInfo rxSignalInfo,
1153 WifiTxVector txVector,
1154 std::vector<bool> perMpduStatus)
1155{
1157 this << psdu << rxSignalInfo << txVector << perMpduStatus.size()
1158 << std::all_of(perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
1159
1160 if (!perMpduStatus.empty())
1161 {
1162 // for A-MPDUs, we get here only once
1163 PreProcessFrame(psdu, txVector);
1164 }
1165
1166 Mac48Address addr1 = psdu->GetAddr1();
1167
1168 if (addr1.IsGroup() || addr1 == m_self)
1169 {
1170 // receive broadcast frames or frames addressed to us only
1171 if (psdu->GetNMpdus() == 1)
1172 {
1173 // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
1174 // then it must contain a single value which must be true (i.e., the MPDU
1175 // has been correctly received)
1176 NS_ASSERT(perMpduStatus.empty() || (perMpduStatus.size() == 1 && perMpduStatus[0]));
1177 // Ack and CTS do not carry Addr2
1178 if (!psdu->GetHeader(0).IsAck() && !psdu->GetHeader(0).IsCts())
1179 {
1180 GetWifiRemoteStationManager()->ReportRxOk(psdu->GetHeader(0).GetAddr2(),
1181 rxSignalInfo,
1182 txVector);
1183 }
1184 ReceiveMpdu(*(psdu->begin()), rxSignalInfo, txVector, perMpduStatus.empty());
1185 }
1186 else
1187 {
1188 EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
1189 }
1190 }
1191 else if (m_promisc)
1192 {
1193 for (const auto& mpdu : *PeekPointer(psdu))
1194 {
1195 if (!mpdu->GetHeader().IsCtl())
1196 {
1197 m_rxMiddle->Receive(mpdu, m_linkId);
1198 }
1199 }
1200 }
1201
1202 if (!perMpduStatus.empty())
1203 {
1204 // for A-MPDUs, we get here only once
1205 PostProcessFrame(psdu, txVector);
1206 }
1207}
1208
1209void
1211{
1212 NS_LOG_FUNCTION(this << psdu << txVector);
1213}
1214
1215void
1217{
1218 NS_LOG_FUNCTION(this << psdu << txVector);
1219
1220 UpdateNav(psdu, txVector);
1221}
1222
1223void
1225{
1226 NS_LOG_FUNCTION(this << psdu << txVector);
1227
1228 if (!psdu->HasNav())
1229 {
1230 return;
1231 }
1232
1233 Time duration = psdu->GetDuration();
1234 NS_LOG_DEBUG("Duration/ID=" << duration);
1235
1236 if (psdu->GetAddr1() == m_self)
1237 {
1238 // When the received frame’s RA is equal to the STA’s own MAC address, the STA
1239 // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
1240 return;
1241 }
1242
1243 // For all other received frames the STA shall update its NAV when the received
1244 // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
1245 Time navEnd = Simulator::Now() + duration;
1246 if (navEnd > m_navEnd)
1247 {
1248 m_navEnd = navEnd;
1249 NS_LOG_DEBUG("Updated NAV=" << m_navEnd);
1250
1251 // A STA that used information from an RTS frame as the most recent basis to update
1252 // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
1253 // primitive is received from the PHY during a NAVTimeout period starting when the
1254 // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
1255 // the RTS frame. NAVTimeout period is equal to:
1256 // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
1257 // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
1258 // rate at which the RTS frame used for the most recent NAV update was received
1259 // (IEEE 802.11-2016 sec. 10.3.2.4)
1260 if (psdu->GetHeader(0).IsRts())
1261 {
1262 WifiTxVector ctsTxVector =
1263 GetWifiRemoteStationManager()->GetCtsTxVector(psdu->GetAddr2(), txVector.GetMode());
1264 Time navResetDelay =
1265 2 * m_phy->GetSifs() +
1270 }
1271 }
1272 NS_LOG_DEBUG("Current NAV=" << m_navEnd);
1273
1274 m_channelAccessManager->NotifyNavStartNow(duration);
1275}
1276
1277void
1284
1285bool
1290
1291void
1293 RxSignalInfo rxSignalInfo,
1294 const WifiTxVector& txVector,
1295 bool inAmpdu)
1296{
1297 NS_LOG_FUNCTION(this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1298 // The received MPDU is either broadcast or addressed to this station
1299 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
1300
1301 double rxSnr = rxSignalInfo.snr;
1302 const WifiMacHeader& hdr = mpdu->GetHeader();
1303
1304 if (hdr.IsCtl())
1305 {
1306 if (hdr.IsRts())
1307 {
1308 NS_ABORT_MSG_IF(inAmpdu, "Received RTS as part of an A-MPDU");
1309
1310 // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1311 // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1312 // - Otherwise, the STA shall not respond with a CTS frame
1313 // (IEEE 802.11-2016 sec. 10.3.2.7)
1314 if (VirtualCsMediumIdle())
1315 {
1316 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", schedule CTS");
1319 this,
1320 hdr,
1321 txVector.GetMode(),
1322 rxSnr);
1323 }
1324 else
1325 {
1326 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", cannot schedule CTS");
1327 }
1328 }
1329 else if (hdr.IsCts() && m_txTimer.IsRunning() &&
1331 {
1332 NS_ABORT_MSG_IF(inAmpdu, "Received CTS as part of an A-MPDU");
1333 NS_ASSERT(hdr.GetAddr1() == m_self);
1334
1335 Mac48Address sender = m_mpdu->GetHeader().GetAddr1();
1336 NS_LOG_DEBUG("Received CTS from=" << sender);
1337
1338 SnrTag tag;
1339 mpdu->GetPacket()->PeekPacketTag(tag);
1340 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
1341 GetWifiRemoteStationManager()->ReportRtsOk(m_mpdu->GetHeader(),
1342 rxSnr,
1343 txVector.GetMode(),
1344 tag.Get());
1345
1346 m_txTimer.Cancel();
1347 m_channelAccessManager->NotifyCtsTimeoutResetNow();
1349 }
1350 else if (hdr.IsAck() && m_mpdu && m_txTimer.IsRunning() &&
1352 {
1353 NS_ASSERT(hdr.GetAddr1() == m_self);
1354 SnrTag tag;
1355 mpdu->GetPacket()->PeekPacketTag(tag);
1356 ReceivedNormalAck(m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get());
1357 m_mpdu = nullptr;
1358 }
1359 }
1360 else if (hdr.IsMgt())
1361 {
1362 NS_ABORT_MSG_IF(inAmpdu, "Received management frame as part of an A-MPDU");
1363
1364 if (hdr.IsBeacon() || hdr.IsProbeResp())
1365 {
1366 // Apply SNR tag for beacon quality measurements
1367 SnrTag tag;
1368 tag.Set(rxSnr);
1369 Ptr<Packet> packet = mpdu->GetPacket()->Copy();
1370 packet->AddPacketTag(tag);
1371 mpdu = Create<WifiMpdu>(packet, hdr);
1372 }
1373
1374 if (hdr.GetAddr1() == m_self)
1375 {
1376 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1377 << ", schedule ACK");
1380 this,
1381 hdr,
1382 txVector,
1383 rxSnr);
1384 }
1385
1386 m_rxMiddle->Receive(mpdu, m_linkId);
1387 }
1388 else if (hdr.IsData() && !hdr.IsQosData())
1389 {
1390 if (hdr.GetAddr1() == m_self)
1391 {
1392 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1393 << ", schedule ACK");
1396 this,
1397 hdr,
1398 txVector,
1399 rxSnr);
1400 }
1401
1402 m_rxMiddle->Receive(mpdu, m_linkId);
1403 }
1404}
1405
1406void
1408 const WifiTxVector& txVector,
1409 const WifiTxVector& ackTxVector,
1410 const RxSignalInfo& rxInfo,
1411 double snr)
1412{
1413 Mac48Address sender = mpdu->GetHeader().GetAddr1();
1414 NS_LOG_DEBUG("Received ACK from=" << sender);
1415
1417
1418 // When fragmentation is used, only update manager when the last fragment is acknowledged
1419 if (!mpdu->GetHeader().IsMoreFragments())
1420 {
1421 GetWifiRemoteStationManager()->ReportRxOk(sender, rxInfo, ackTxVector);
1422 GetWifiRemoteStationManager()->ReportDataOk(mpdu,
1423 rxInfo.snr,
1424 ackTxVector.GetMode(),
1425 snr,
1426 txVector);
1427 }
1428 // cancel the timer
1429 m_txTimer.Cancel();
1430 m_channelAccessManager->NotifyAckTimeoutResetNow();
1431
1432 // The CW shall be reset to aCWmin after every successful attempt to transmit
1433 // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1435
1436 if (mpdu->GetHeader().IsMoreFragments())
1437 {
1438 // replace the current fragment with the next one
1439 m_dcf->GetWifiMacQueue()->Replace(mpdu, GetNextFragment());
1440 m_moreFragments = true;
1441 }
1442 else
1443 {
1444 // the MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1445 DequeueMpdu(mpdu);
1446 }
1447
1449}
1450
1451void
1453{
1454 NS_LOG_FUNCTION(this << *mpdu);
1455
1456 // inform the MAC that the transmission was successful
1458 {
1459 m_ackedMpduCallback(mpdu);
1460 }
1461}
1462
1463void
1465 const RxSignalInfo& rxSignalInfo,
1466 const WifiTxVector& txVector,
1467 const std::vector<bool>& perMpduStatus)
1468{
1469 NS_ASSERT_MSG(false, "A non-QoS station should not receive an A-MPDU");
1470}
1471
1472} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition callback.h:555
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
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...
Ptr< WifiMpdu > m_mpdu
the MPDU being transmitted
virtual void SetAckManager(Ptr< WifiAckManager > ackManager)
Set the Acknowledgment Manager to use.
void NotifyOffNow()
This method is typically invoked by the PhyListener to notify the MAC layer that the device has been ...
virtual void NotifyInternalCollision(Ptr< Txop > txop)
Notify that an internal collision has occurred for the given Txop.
static TypeId GetTypeId()
Get the type ID.
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
DroppedMpdu m_droppedMpduCallback
the dropped MPDU callback
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the MAC layer to use.
virtual void ResetPhy()
Remove WifiPhy associated with this FrameExchangeManager.
virtual void UpdateNav(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Update the NAV, if needed, based on the Duration/ID of the given psdu.
void SendMpduWithProtection(Ptr< WifiMpdu > mpdu, WifiTxParameters &txParams)
Send an MPDU with the given TX parameters (with the specified protection).
Ptr< WifiAckManager > m_ackManager
Acknowledgment manager.
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.
Ptr< Packet > m_fragmentedPacket
the MSDU being fragmented
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Set the callback to invoke when an MPDU is dropped.
virtual void Reset()
Reset this frame exchange manager.
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 TransmissionFailed()
Take necessary actions upon a transmission failure.
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::optional< std::reference_wrapper< const WifiMacHeader > > GetReceivedMacHdr() const
WifiTxTimer m_txTimer
the timer set upon frame transmission
virtual void SendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiMode rtsTxMode, double rtsSnr)
Send CTS after receiving RTS.
std::set< Mac48Address > m_protectedStas
STAs that have replied to an RTS in this TXOP.
virtual Time GetRtsDurationId(const WifiTxVector &rtsTxVector, Time txDuration, Time response) const
Compute how to set the Duration/ID field of an RTS frame to send to protect a frame transmitted with ...
virtual void RetransmitMpduAfterMissedAck(Ptr< WifiMpdu > mpdu) const
Retransmit an MPDU that was not acknowledged.
Mac48Address GetAddress() const
Get the MAC address.
Ptr< WifiProtectionManager > m_protectionManager
Protection manager.
OngoingRxInfo m_ongoingRxInfo
information about the MAC header of the MPDU being received
virtual void ProtectionCompleted()
Transmit prepared frame upon successful protection mechanism.
virtual void ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector)
Forward an MPDU down to the PHY layer.
virtual void SetLinkId(uint8_t linkId)
Set the ID of the link this Frame Exchange Manager is associated with.
virtual bool VirtualCsMediumIdle() const
void SendRts(const WifiTxParameters &txParams)
Send RTS to begin RTS-CTS-Data-Ack transaction.
virtual void NotifyReceivedNormalAck(Ptr< WifiMpdu > mpdu)
Notify other components that an MPDU was acknowledged.
virtual void NotifyChannelReleased(Ptr< Txop > txop)
Notify the given Txop that channel has been released.
virtual void NormalAckTimeout(Ptr< WifiMpdu > mpdu, const WifiTxVector &txVector)
Called when the Ack timeout expires.
virtual void NotifySwitchingStartNow(Time duration)
virtual void SetBssid(Mac48Address bssid)
Set the Basic Service Set Identification.
void SendCtsToSelf(const WifiTxParameters &txParams)
Send CTS for a CTS-to-self mechanism.
virtual void CtsTimeout(Ptr< WifiMpdu > rts, const WifiTxVector &txVector)
Called when the CTS timeout expires.
virtual void ReceivedMacHdr(const WifiMacHeader &macHdr, const WifiTxVector &txVector, Time psduDuration)
Store information about the MAC header of the MPDU being received.
virtual void CalculateProtectionTime(WifiProtection *protection) const
Calculate the time required to protect a frame according to the given protection method.
std::optional< std::reference_wrapper< const OngoingRxInfo > > GetOngoingRxInfo() const
virtual void SetAddress(Mac48Address address)
Set the MAC address.
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.
virtual void NavResetTimeout()
Reset the NAV upon expiration of the NAV reset timer.
const std::set< Mac48Address > & GetProtectedStas() const
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
bool IsPromisc() const
Check if the device is operating in promiscuous mode.
void SendMpdu()
Send the current MPDU, which can be acknowledged by a Normal Ack.
virtual void EndReceiveAmpdu(Ptr< const WifiPsdu > psdu, const RxSignalInfo &rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &perMpduStatus)
This method is called when the reception of an A-MPDU including multiple MPDUs is completed.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
virtual void TransmissionSucceeded()
Take necessary actions upon a transmission success.
Ptr< Txop > m_dcf
the DCF/EDCAF that gained channel access
Ptr< WifiPhy > m_phy
the PHY layer on this station
Ptr< WifiMpdu > GetFirstFragmentIfNeeded(Ptr< WifiMpdu > mpdu)
Fragment the given MPDU if needed.
Ptr< WifiMpdu > GetNextFragment()
Get the next fragment of the current MSDU.
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...
void SetAckedMpduCallback(AckedMpdu callback)
Set the callback to invoke when an MPDU is successfully acked.
virtual void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
virtual Time GetFrameDurationId(const WifiMacHeader &header, uint32_t size, const WifiTxParameters &txParams, Ptr< Packet > fragmentedPacket) const
Compute how to set the Duration/ID field of a frame being transmitted with the given TX parameters.
virtual Time GetCtsToSelfDurationId(const WifiTxVector &ctsTxVector, Time txDuration, Time response) const
Compute how to set the Duration/ID field of a CTS-to-self frame to send to protect a frame transmitte...
void DoSendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiTxVector &ctsTxVector, double rtsSnr)
Send CTS after receiving RTS.
void Receive(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > perMpduStatus)
This method is intended to be called by the PHY layer every time an MPDU is received and also when th...
Mac48Address m_bssid
BSSID address (Mac48Address)
virtual void SetWifiPhy(const Ptr< WifiPhy > phy)
Set the PHY layer to use.
AckedMpdu m_ackedMpduCallback
the acknowledged MPDU callback
virtual void FinalizeMacHeader(Ptr< const WifiPsdu > psdu)
Finalize the MAC header of the MPDUs in the given PSDU before transmission.
virtual void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
virtual uint32_t GetPsduSize(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector) const
Get the size in bytes of the given MPDU, which is to be transmitted with the given TXVECTOR.
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
virtual void ReceivedNormalAck(Ptr< WifiMpdu > mpdu, const WifiTxVector &txVector, const WifiTxVector &ackTxVector, const RxSignalInfo &rxInfo, double snr)
Perform the actions needed when a Normal Ack is received.
bool m_promisc
Flag if the device is operating in promiscuous mode.
void NotifySleepNow()
This method is typically invoked by the PhyListener to notify the MAC layer that the device has been ...
virtual void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu)
This method handles the reception of an MPDU (possibly included in an A-MPDU)
virtual void SetChannelAccessManager(const Ptr< ChannelAccessManager > channelAccessManager)
Set the channel access manager to use.
virtual bool StartTransmission(Ptr< Txop > dcf, MHz_u allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
bool m_moreFragments
true if a fragment has to be sent after a SIFS
void SetPromisc()
Enable promiscuous mode.
MHz_u m_allowedWidth
the allowed width for the current transmission
virtual void PsduRxError(Ptr< const WifiPsdu > psdu)
This method is called when the reception of a PSDU fails.
Time m_navEnd
NAV expiration time.
virtual void SetMacTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set the MAC TX Middle to use.
virtual void SetMacRxMiddle(const Ptr< MacRxMiddle > rxMiddle)
Set the MAC RX Middle to use.
virtual void SetProtectionManager(Ptr< WifiProtectionManager > protectionManager)
Set the Protection Manager to use.
Mac48Address GetBssid() const
Get the Basic Service Set Identification.
void DoDispose() override
Destructor implementation.
WifiTxParameters m_txParams
the TX parameters for the current frame
virtual void RxStartIndication(WifiTxVector txVector, Time psduDuration)
EventId m_navResetEvent
the event to reset the NAV after an RTS
const WifiTxTimer & GetWifiTxTimer() const
Get a const reference to the WifiTxTimer object.
virtual Time GetTxDuration(uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters &txParams) const
Get the updated TX duration of the frame associated with the given TX parameters if the size of the P...
an EUI-48 address
bool IsGroup() const
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
A base class which provides memory management and object aggregation.
Definition object.h:78
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition packet.h:850
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition packet.cc:227
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
void Set(double snr)
Set the SNR to the given value.
Definition snr-tag.cc:73
double Get() const
Return the SNR value.
Definition snr-tag.cc:79
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
@ US
microsecond
Definition nstime.h:107
@ MS
millisecond
Definition nstime.h:106
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
Definition nstime.h:331
void UpdateFailedCw(uint8_t linkId)
Update the value of the CW variable for the given link to take into account a transmission failure.
Definition txop.cc:371
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition txop.cc:264
void ResetCw(uint8_t linkId)
Update the value of the CW variable for the given link to take into account a transmission success or...
Definition txop.cc:362
virtual void NotifyChannelAccessed(uint8_t linkId, Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
Definition txop.cc:739
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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.
Implements the IEEE 802.11 MAC header.
bool IsAck() const
Return true if the header is an Ack header.
bool IsCts() const
Return true if the header is a CTS header.
bool IsBeacon() const
Return true if the header is a Beacon header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
bool IsMoreFragments() const
Return if the More Fragment bit is set.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
bool IsMgt() const
Return true if the Type is Management.
bool IsCtl() const
Return true if the Type is Control.
Time GetDuration() const
Return the duration from the Duration/ID field (Time object).
virtual uint32_t GetSize() const
Return the size of the WifiMacHeader in octets.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsProbeResp() const
Return true if the header is a Probe Response header.
void SetMoreFragments()
Set the More Fragment bit in the Frame Control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
virtual const char * GetTypeString() const
Return a string corresponds to the header type.
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
bool IsData() const
Return true if the Type is DATA.
bool IsRts() const
Return true if the header is a RTS header.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
uint8_t GetFragmentNumber() const
Return the fragment number of the header.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetFragmentNumber(uint8_t frag)
Set the fragment number of the header.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition wifi-mac.cc:686
represent a single transmission mode
Definition wifi-mode.h:40
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.
Definition wifi-phy.cc:1792
Time GetSlot() const
Return the slot duration for this PHY.
Definition wifi-phy.cc:835
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition wifi-phy.cc:823
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:478
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1572
Ptr< WifiPhyStateHelper > GetState() const
Return the WifiPhyStateHelper of this PHY.
Definition wifi-phy.cc:466
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1063
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:472
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1565
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::optional< Time > m_txDuration
TX duration of the frame.
const PsduInfoMap & GetPsduInfoMap() const
Get a const reference to the map containing information about PSDUs.
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
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void AddMpdu(Ptr< const WifiMpdu > mpdu)
Record that an MPDU is being added to the current frame.
void Clear()
Reset the TX parameters.
This class is used to handle the timer that a station starts when transmitting a frame that solicits ...
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.
void Reschedule(const Time &delay)
Reschedule the timer to time out the given amount of time from the moment this function is called.
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.
MHz_u GetChannelWidth() const
#define PSDU_DURATION_SAFEGUARD
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
@ STA
Definition wifi-mac.h:58
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition wifi-mac.h:73
@ WIFI_PM_SWITCHING_TO_ACTIVE
@ WIFI_PM_POWERSAVE
@ WIFI_PM_SWITCHING_TO_PS
@ WIFI_PM_ACTIVE
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
uint32_t GetRtsSize()
Return the total RTS size (including FCS trailer).
Definition wifi-utils.cc:95
double MHz_u
MHz weak type.
Definition wifi-units.h:31
@ WIFI_MAC_CTL_RTS
@ WIFI_MAC_CTL_CTS
@ WIFI_MAC_CTL_ACK
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
uint32_t GetAckSize()
Return the total Ack size (including FCS trailer).
Definition wifi-utils.cc:50
uint32_t GetCtsSize()
Return the total CTS size (including FCS trailer).
ns3::Time timeout
Time endOfPsduRx
time when reception of PSDU ends
std::optional< WifiMacHeader > macHdr
MAC header of the MPDU being received.
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:72
double snr
SNR in linear scale.
Definition wifi-types.h:73
WifiAcknowledgment is an abstract base struct.
const Method method
acknowledgment method
std::optional< Time > acknowledgmentTime
time required by the acknowledgment method
WifiCtsToSelfProtection specifies that CTS-to-self protection method is used.
WifiNormalAck specifies that acknowledgment via Normal Ack is required.
WifiProtection is an abstract base struct.
std::optional< Time > protectionTime
time required by the protection method
const Method method
protection method
WifiRtsCtsProtection specifies that RTS/CTS protection method is used.