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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Stefano Avallone <stavallo@unina.it>
18 */
19
21
22#include "snr-tag.h"
23#include "sta-wifi-mac.h"
24#include "wifi-mac-queue.h"
25#include "wifi-mac-trailer.h"
26#include "wifi-utils.h"
27
28#include "ns3/abort.h"
29#include "ns3/log.h"
30
31#undef NS_LOG_APPEND_CONTEXT
32#define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
33
34// Time (in nanoseconds) to be added to the PSDU duration to yield the duration
35// of the timer that is started when the PHY indicates the start of the reception
36// of a frame and we are waiting for a response.
37#define PSDU_DURATION_SAFEGUARD 400
38
39namespace ns3
40{
41
42NS_LOG_COMPONENT_DEFINE("FrameExchangeManager");
43
44NS_OBJECT_ENSURE_REGISTERED(FrameExchangeManager);
45
46TypeId
48{
49 static TypeId tid = TypeId("ns3::FrameExchangeManager")
51 .AddConstructor<FrameExchangeManager>()
52 .SetGroupName("Wifi");
53 return tid;
54}
55
57 : m_navEnd(Seconds(0)),
58 m_linkId(0),
59 m_allowedWidth(0),
60 m_promisc(false),
61 m_moreFragments(false)
62{
63 NS_LOG_FUNCTION(this);
64}
65
67{
69}
70
71void
73{
74 NS_LOG_FUNCTION(this);
77 {
79 }
81 m_mpdu = nullptr;
83 m_dcf = nullptr;
84}
85
86void
88{
89 NS_LOG_FUNCTION(this);
90 Reset();
91 m_fragmentedPacket = nullptr;
92 m_mac = nullptr;
93 m_txMiddle = nullptr;
94 m_rxMiddle = nullptr;
95 m_channelAccessManager = nullptr;
96 m_protectionManager = nullptr;
97 m_ackManager = nullptr;
98 ResetPhy();
100}
101
102void
104{
105 NS_LOG_FUNCTION(this << protectionManager);
106 m_protectionManager = protectionManager;
107}
108
111{
112 return m_protectionManager;
113}
114
115void
117{
118 NS_LOG_FUNCTION(this << ackManager);
119 m_ackManager = ackManager;
120}
121
124{
125 return m_ackManager;
126}
127
128void
130{
131 NS_LOG_FUNCTION(this << +linkId);
132 m_linkId = linkId;
133}
134
135void
137{
138 NS_LOG_FUNCTION(this << mac);
139 m_mac = mac;
140}
141
142void
144{
145 NS_LOG_FUNCTION(this << txMiddle);
146 m_txMiddle = txMiddle;
147}
148
149void
151{
152 NS_LOG_FUNCTION(this << rxMiddle);
153 m_rxMiddle = rxMiddle;
154}
155
156void
158{
159 NS_LOG_FUNCTION(this << channelAccessManager);
160 m_channelAccessManager = channelAccessManager;
161}
162
165{
167}
168
169void
171{
172 NS_LOG_FUNCTION(this << phy);
173 m_phy = phy;
174 m_phy->TraceConnectWithoutContext("PhyRxPayloadBegin",
177}
178
179void
181{
182 NS_LOG_FUNCTION(this);
183 if (m_phy)
184 {
186 "PhyRxPayloadBegin",
188 if (m_phy->GetState())
189 {
194 std::vector<bool>>());
195 }
196 m_phy = nullptr;
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
229void
231{
232 NS_LOG_FUNCTION(this << &callback);
233 m_droppedMpduCallback = callback;
234}
235
236void
238{
239 NS_LOG_FUNCTION(this << &callback);
240 m_ackedMpduCallback = callback;
241}
242
243void
245{
246 m_promisc = true;
247}
248
249bool
251{
252 return m_promisc;
253}
254
255const WifiTxTimer&
257{
258 return m_txTimer;
259}
260
261void
263{
265 {
267 }
268}
269
270void
272{
273 NS_LOG_FUNCTION(this << "PSDU reception started for " << psduDuration.As(Time::US)
274 << " (txVector: " << txVector << ")");
275
277 "The TX timer and the NAV reset event cannot be both running");
278
279 // No need to reschedule timeouts if PSDU duration is null. In this case,
280 // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered)
281 // and CCA will take over
282 if (m_txTimer.IsRunning() && psduDuration.IsStrictlyPositive())
283 {
284 // we are waiting for a response and something arrived
285 NS_LOG_DEBUG("Rescheduling timeout event");
287 // PHY has switched to RX, so we can reset the ack timeout
289 }
290
292 {
294 }
295}
296
297bool
299{
300 NS_LOG_FUNCTION(this << dcf << allowedWidth);
301
303 if (m_txTimer.IsRunning())
304 {
306 }
307 m_dcf = dcf;
308 m_allowedWidth = allowedWidth;
309
310 Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue();
311
312 // Even though channel access is requested when the queue is not empty, at
313 // the time channel access is granted the lifetime of the packet might be
314 // expired and the queue might be empty.
315 queue->WipeAllExpiredMpdus();
316
317 Ptr<WifiMpdu> mpdu = queue->Peek(m_linkId);
318
319 if (!mpdu)
320 {
321 NS_LOG_DEBUG("Queue empty");
323 m_dcf = nullptr;
324 return false;
325 }
326
328
329 NS_ASSERT(mpdu->GetHeader().IsData() || mpdu->GetHeader().IsMgt());
330
331 // assign a sequence number if this is not a fragment nor a retransmission
332 if (!mpdu->IsFragment() && !mpdu->GetHeader().IsRetry())
333 {
334 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader());
335 mpdu->AssignSeqNo(sequence);
336 }
337
338 NS_LOG_DEBUG("MPDU payload size=" << mpdu->GetPacketSize()
339 << ", to=" << mpdu->GetHeader().GetAddr1()
340 << ", seq=" << mpdu->GetHeader().GetSequenceControl());
341
342 // check if the MSDU needs to be fragmented
343 mpdu = GetFirstFragmentIfNeeded(mpdu);
344
347 WifiTxParameters txParams;
348 txParams.m_txVector =
350 txParams.m_protection = m_protectionManager->TryAddMpdu(mpdu, txParams);
351 txParams.m_acknowledgment = m_ackManager->TryAddMpdu(mpdu, txParams);
352 txParams.AddMpdu(mpdu);
353 UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
354
355 SendMpduWithProtection(mpdu, txParams);
356
357 return true;
358}
359
362{
363 NS_LOG_FUNCTION(this << *mpdu);
364
365 if (mpdu->IsFragment())
366 {
367 // a fragment cannot be further fragmented
369 }
370 else if (GetWifiRemoteStationManager()->NeedFragmentation(mpdu))
371 {
372 NS_LOG_DEBUG("Fragmenting the MSDU");
373 m_fragmentedPacket = mpdu->GetPacket()->Copy();
374 // create the first fragment
376 0,
377 GetWifiRemoteStationManager()->GetFragmentSize(mpdu, 0));
378 // enqueue the first fragment
379 Ptr<WifiMpdu> item = Create<WifiMpdu>(fragment, mpdu->GetHeader());
380 item->GetHeader().SetMoreFragments();
381 m_mac->GetTxopQueue(mpdu->GetQueueAc())->Replace(mpdu, item);
382 return item;
383 }
384 return mpdu;
385}
386
387void
389{
390 NS_LOG_FUNCTION(this << *mpdu << &txParams);
391
392 m_mpdu = mpdu;
393 m_txParams = std::move(txParams);
394
395 // If protection is required, the MPDU must be stored in some queue because
396 // it is not put back in a queue if the RTS/CTS exchange fails
398 m_mpdu->GetHeader().IsCtl() || m_mpdu->IsQueued());
399
400 // Make sure that the acknowledgment time has been computed, so that SendRts()
401 // and SendCtsToSelf() can reuse this value.
403
404 if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min())
405 {
407 }
408
409 // Set QoS Ack policy if this is a QoS data frame
411
412 if (m_mpdu->IsQueued())
413 {
414 m_mpdu->SetInFlight(m_linkId);
415 }
416
418
420 {
421 // we are done with frames that do not require acknowledgment
422 m_mpdu = nullptr;
423 }
424}
425
426void
428{
429 NS_LOG_FUNCTION(this << &txParams);
430
431 switch (txParams.m_protection->method)
432 {
434 SendRts(txParams);
435 break;
437 SendCtsToSelf(txParams);
438 break;
441 break;
442 default:
443 NS_ABORT_MSG("Unknown protection type: " << txParams.m_protection.get());
444 }
445}
446
447void
449{
450 NS_LOG_FUNCTION(this);
452 m_sentRtsTo.clear();
454 SendMpdu();
455}
456
457const std::set<Mac48Address>&
459{
460 return m_protectedStas;
461}
462
463void
465{
466 NS_LOG_FUNCTION(this);
467
470 m_phy->GetPhyBand());
471
473
475 {
477
478 if (!m_mpdu->GetHeader().IsQosData() ||
479 m_mpdu->GetHeader().GetQosAckPolicy() == WifiMacHeader::NO_ACK)
480 {
481 // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
483 }
484 }
486 {
487 m_mpdu->GetHeader().SetDuration(
488 GetFrameDurationId(m_mpdu->GetHeader(),
492
493 // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
494 // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
495 // aRxPHYStartDelay equals the time to transmit the PHY header.
496 WifiNormalAck* normalAcknowledgment =
497 static_cast<WifiNormalAck*>(m_txParams.m_acknowledgment.get());
498
499 Time timeout =
500 txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
504 timeout,
506 this,
507 m_mpdu,
510 }
511 else
512 {
513 NS_ABORT_MSG("Unable to handle the selected acknowledgment method ("
514 << m_txParams.m_acknowledgment.get() << ")");
515 }
516
517 // transmit the MPDU
519}
520
521void
523{
524 NS_LOG_FUNCTION(this << *mpdu << txVector);
525
526 auto psdu = Create<WifiPsdu>(mpdu, false);
527 FinalizeMacHeader(psdu);
528 m_phy->Send(psdu, txVector);
529}
530
531void
533{
534 NS_LOG_FUNCTION(this << psdu);
535
536 if (m_mac->GetTypeOfStation() != STA)
537 {
538 return;
539 }
540
541 auto pmMode = StaticCast<StaWifiMac>(m_mac)->GetPmMode(m_linkId);
542
543 for (const auto& mpdu : *PeekPointer(psdu))
544 {
545 switch (pmMode)
546 {
547 case WIFI_PM_ACTIVE:
549 mpdu->GetHeader().SetNoPowerManagement();
550 break;
553 mpdu->GetHeader().SetPowerManagement();
554 break;
555 default:
556 NS_ABORT_MSG("Unknown PM mode: " << +pmMode);
557 }
558 }
559}
560
561void
563{
564 NS_LOG_DEBUG(this << *mpdu);
565
566 if (mpdu->IsQueued())
567 {
568 m_mac->GetTxopQueue(mpdu->GetQueueAc())->DequeueIfQueued({mpdu});
569 }
570}
571
574{
575 return mpdu->GetSize();
576}
577
578void
580{
581 NS_LOG_FUNCTION(this << protection);
582 NS_ASSERT(protection);
583
584 if (protection->method == WifiProtection::NONE)
585 {
586 protection->protectionTime = Seconds(0);
587 }
588 else if (protection->method == WifiProtection::RTS_CTS)
589 {
590 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*>(protection);
591 rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration(GetRtsSize(),
592 rtsCtsProtection->rtsTxVector,
593 m_phy->GetPhyBand()) +
595 rtsCtsProtection->ctsTxVector,
596 m_phy->GetPhyBand()) +
597 2 * m_phy->GetSifs();
598 }
599 else if (protection->method == WifiProtection::CTS_TO_SELF)
600 {
601 WifiCtsToSelfProtection* ctsToSelfProtection =
602 static_cast<WifiCtsToSelfProtection*>(protection);
603 ctsToSelfProtection->protectionTime =
605 ctsToSelfProtection->ctsTxVector,
606 m_phy->GetPhyBand()) +
607 m_phy->GetSifs();
608 }
609}
610
611void
613{
614 NS_LOG_FUNCTION(this << acknowledgment);
615 NS_ASSERT(acknowledgment);
616
617 if (acknowledgment->method == WifiAcknowledgment::NONE)
618 {
619 acknowledgment->acknowledgmentTime = Seconds(0);
620 }
621 else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
622 {
623 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*>(acknowledgment);
624 normalAcknowledgment->acknowledgmentTime =
626 normalAcknowledgment->ackTxVector,
627 m_phy->GetPhyBand());
628 }
629}
630
631Time
633 Mac48Address receiver,
634 const WifiTxParameters& txParams) const
635{
636 return m_phy->CalculateTxDuration(ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand());
637}
638
639void
641{
642 txParams.m_txDuration = GetTxDuration(txParams.GetSize(receiver), receiver, txParams);
643}
644
645Time
647 uint32_t size,
648 const WifiTxParameters& txParams,
649 Ptr<Packet> fragmentedPacket) const
650{
651 NS_LOG_FUNCTION(this << header << size << &txParams << fragmentedPacket);
652
653 NS_ASSERT(txParams.m_acknowledgment &&
654 txParams.m_acknowledgment->acknowledgmentTime != Time::Min());
655 Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
656
657 // if the current frame is a fragment followed by another fragment, we have to
658 // update the Duration/ID to cover the next fragment and the corresponding Ack
659 if (header.IsMoreFragments())
660 {
661 uint32_t payloadSize = size - header.GetSize() - WIFI_MAC_FCS_LENGTH;
662 uint32_t nextFragmentOffset = (header.GetFragmentNumber() + 1) * payloadSize;
663 uint32_t nextFragmentSize =
664 std::min(fragmentedPacket->GetSize() - nextFragmentOffset, payloadSize);
665 WifiTxVector ackTxVector =
667
668 durationId +=
669 2 * m_phy->GetSifs() +
671 m_phy->CalculateTxDuration(nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand());
672 }
673 return durationId;
674}
675
676Time
678 Time txDuration,
679 Time response) const
680{
681 NS_LOG_FUNCTION(this << rtsTxVector << txDuration << response);
682
683 WifiTxVector ctsTxVector;
684 ctsTxVector = GetWifiRemoteStationManager()->GetCtsTxVector(m_self, rtsTxVector.GetMode());
685
686 return m_phy->GetSifs() +
687 m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()) /* CTS */
688 + m_phy->GetSifs() + txDuration + response;
689}
690
691void
693{
694 NS_LOG_FUNCTION(this << &txParams);
695
696 NS_ASSERT(txParams.GetPsduInfoMap().size() == 1);
697 Mac48Address receiver = txParams.GetPsduInfoMap().begin()->first;
698
699 WifiMacHeader rts;
701 rts.SetDsNotFrom();
702 rts.SetDsNotTo();
703 rts.SetNoRetry();
704 rts.SetNoMoreFragments();
705 rts.SetAddr1(receiver);
706 rts.SetAddr2(m_self);
707
708 NS_ASSERT(txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
709 WifiRtsCtsProtection* rtsCtsProtection =
710 static_cast<WifiRtsCtsProtection*>(txParams.m_protection.get());
711
712 NS_ASSERT(txParams.m_txDuration != Time::Min());
713 rts.SetDuration(GetRtsDurationId(rtsCtsProtection->rtsTxVector,
714 txParams.m_txDuration,
715 txParams.m_acknowledgment->acknowledgmentTime));
716 Ptr<WifiMpdu> mpdu = Create<WifiMpdu>(Create<Packet>(), rts);
717
718 // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
719 // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
720 // aRxPHYStartDelay equals the time to transmit the PHY header.
722 rtsCtsProtection->rtsTxVector,
723 m_phy->GetPhyBand()) +
724 m_phy->GetSifs() + m_phy->GetSlot() +
728 timeout,
730 this,
731 mpdu,
732 rtsCtsProtection->rtsTxVector);
734 NS_ASSERT(m_sentRtsTo.empty());
735 m_sentRtsTo = {receiver};
736
737 ForwardMpduDown(mpdu, rtsCtsProtection->rtsTxVector);
738}
739
740void
742 WifiTxVector& ctsTxVector,
743 double rtsSnr)
744{
745 NS_LOG_FUNCTION(this << rtsHdr << ctsTxVector << rtsSnr);
746
747 WifiMacHeader cts;
749 cts.SetDsNotFrom();
750 cts.SetDsNotTo();
751 cts.SetNoMoreFragments();
752 cts.SetNoRetry();
753 cts.SetAddr1(rtsHdr.GetAddr2());
754 Time duration = rtsHdr.GetDuration() - m_phy->GetSifs() -
756 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
757 if (duration.IsStrictlyNegative())
758 {
759 duration = Seconds(0);
760 }
761 cts.SetDuration(duration);
762
763 Ptr<Packet> packet = Create<Packet>();
764
765 SnrTag tag;
766 tag.Set(rtsSnr);
767 packet->AddPacketTag(tag);
768
769 // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
770 ForwardMpduDown(Create<WifiMpdu>(packet, cts), ctsTxVector);
771}
772
773void
775 WifiMode rtsTxMode,
776 double rtsSnr)
777{
778 NS_LOG_FUNCTION(this << rtsHdr << rtsTxMode << rtsSnr);
779
780 WifiTxVector ctsTxVector =
782 DoSendCtsAfterRts(rtsHdr, ctsTxVector, rtsSnr);
783}
784
785Time
787 Time txDuration,
788 Time response) const
789{
790 NS_LOG_FUNCTION(this << ctsTxVector << txDuration << response);
791
792 return m_phy->GetSifs() + txDuration + response;
793}
794
795void
797{
798 NS_LOG_FUNCTION(this << &txParams);
799
800 WifiMacHeader cts;
802 cts.SetDsNotFrom();
803 cts.SetDsNotTo();
804 cts.SetNoMoreFragments();
805 cts.SetNoRetry();
806 cts.SetAddr1(m_self);
807
808 NS_ASSERT(txParams.m_protection &&
809 txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
810 WifiCtsToSelfProtection* ctsToSelfProtection =
811 static_cast<WifiCtsToSelfProtection*>(txParams.m_protection.get());
812
813 NS_ASSERT(txParams.m_txDuration != Time::Min());
814 cts.SetDuration(GetCtsToSelfDurationId(ctsToSelfProtection->ctsTxVector,
815 txParams.m_txDuration,
816 txParams.m_acknowledgment->acknowledgmentTime));
817
818 ForwardMpduDown(Create<WifiMpdu>(Create<Packet>(), cts), ctsToSelfProtection->ctsTxVector);
819
820 Time ctsDuration = m_phy->CalculateTxDuration(GetCtsSize(),
821 ctsToSelfProtection->ctsTxVector,
822 m_phy->GetPhyBand());
823 Simulator::Schedule(ctsDuration + m_phy->GetSifs(),
825 this);
826}
827
828void
830 const WifiTxVector& dataTxVector,
831 double dataSnr)
832{
833 NS_LOG_FUNCTION(this << hdr << dataTxVector << dataSnr);
834
835 WifiTxVector ackTxVector =
837 WifiMacHeader ack;
839 ack.SetDsNotFrom();
840 ack.SetDsNotTo();
841 ack.SetNoRetry();
842 ack.SetNoMoreFragments();
843 ack.SetAddr1(hdr.GetAddr2());
844 // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
845 // minus the time to transmit the Ack frame and its SIFS interval
846 Time duration = hdr.GetDuration() - m_phy->GetSifs() -
848 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
849 if (duration.IsStrictlyNegative())
850 {
851 duration = Seconds(0);
852 }
853 ack.SetDuration(duration);
854
855 Ptr<Packet> packet = Create<Packet>();
856
857 SnrTag tag;
858 tag.Set(dataSnr);
859 packet->AddPacketTag(tag);
860
861 ForwardMpduDown(Create<WifiMpdu>(packet, ack), ackTxVector);
862}
863
866{
867 NS_LOG_FUNCTION(this);
868 NS_ASSERT(m_mpdu->GetHeader().IsMoreFragments());
869
870 WifiMacHeader& hdr = m_mpdu->GetHeader();
872
873 uint32_t startOffset = hdr.GetFragmentNumber() * m_mpdu->GetPacketSize();
874 uint32_t size = m_fragmentedPacket->GetSize() - startOffset;
875
876 if (size > m_mpdu->GetPacketSize())
877 {
878 // this is not the last fragment
879 size = m_mpdu->GetPacketSize();
880 hdr.SetMoreFragments();
881 }
882 else
883 {
884 hdr.SetNoMoreFragments();
885 }
886
887 return Create<WifiMpdu>(m_fragmentedPacket->CreateFragment(startOffset, size), hdr);
888}
889
890void
892{
893 NS_LOG_FUNCTION(this);
894
895 // Upon a transmission success, a non-QoS station transmits the next fragment,
896 // if any, or releases the channel, otherwise
897 if (m_moreFragments)
898 {
899 NS_LOG_DEBUG("Schedule transmission of next fragment in a SIFS");
902 this,
903 m_dcf,
905 m_moreFragments = false;
906 }
907 else
908 {
910 m_dcf = nullptr;
911 }
912}
913
914void
916{
917 NS_LOG_FUNCTION(this);
918 // A non-QoS station always releases the channel upon a transmission failure
920 m_dcf = nullptr;
921}
922
923void
925{
926 NS_LOG_FUNCTION(this << txop);
927 txop->NotifyChannelReleased(m_linkId);
928 m_protectedStas.clear();
929}
930
931void
933{
934 NS_LOG_FUNCTION(this << *mpdu << txVector);
935
937
938 if (!GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
939 {
940 NS_LOG_DEBUG("Missed Ack, discard MPDU");
942 // Dequeue the MPDU if it is stored in a queue
943 DequeueMpdu(mpdu);
946 }
947 else
948 {
949 NS_LOG_DEBUG("Missed Ack, retransmit MPDU");
950 if (mpdu->IsQueued()) // the MPDU may have been removed due to lifetime expiration
951 {
952 mpdu = m_mac->GetTxopQueue(mpdu->GetQueueAc())->GetOriginal(mpdu);
953 mpdu->ResetInFlight(m_linkId);
954 }
955 mpdu->GetHeader().SetRetry();
958 }
959
960 m_mpdu = nullptr;
962}
963
964void
966{
967 NS_LOG_FUNCTION(this << *mpdu);
968}
969
970void
972{
973 NS_LOG_FUNCTION(this << *rts << txVector);
974
975 DoCtsTimeout(Create<WifiPsdu>(m_mpdu, true));
976 m_mpdu = nullptr;
977}
978
979void
981{
982 NS_LOG_FUNCTION(this << *psdu);
983
984 m_sentRtsTo.clear();
985 for (const auto& mpdu : *PeekPointer(psdu))
986 {
987 if (mpdu->IsQueued())
988 {
989 mpdu->ResetInFlight(m_linkId);
990 }
991 }
992
993 GetWifiRemoteStationManager()->ReportRtsFailed(psdu->GetHeader(0));
994
995 if (!GetWifiRemoteStationManager()->NeedRetransmission(*psdu->begin()))
996 {
997 NS_LOG_DEBUG("Missed CTS, discard MPDU(s)");
999 for (const auto& mpdu : *PeekPointer(psdu))
1000 {
1001 // Dequeue the MPDU if it is stored in a queue
1002 DequeueMpdu(mpdu);
1004 }
1006 }
1007 else
1008 {
1009 NS_LOG_DEBUG("Missed CTS, retransmit MPDU(s)");
1011 }
1012 // Make the sequence numbers of the MPDUs available again if the MPDUs have never
1013 // been transmitted, both in case the MPDUs have been discarded and in case the
1014 // MPDUs have to be transmitted (because a new sequence number is assigned to
1015 // MPDUs that have never been transmitted and are selected for transmission)
1017
1019}
1020
1021void
1023{
1024 NS_LOG_FUNCTION(this << *psdu);
1025
1026 NS_ASSERT_MSG(psdu->GetNMpdus() == 1, "A-MPDUs should be handled by the HT FEM override");
1027 auto mpdu = *psdu->begin();
1028
1029 // the MPDU should be still in the DCF queue, unless it expired.
1030 // If the MPDU has never been transmitted and is not in-flight, it will be assigned
1031 // a sequence number again the next time we try to transmit it. Therefore, we need to
1032 // make its sequence number available again
1033 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
1034 {
1035 mpdu->UnassignSeqNo();
1036 m_txMiddle->SetSequenceNumberFor(&mpdu->GetOriginal()->GetHeader());
1037 }
1038}
1039
1040void
1042{
1043 NS_LOG_FUNCTION(this);
1044
1045 // For internal collisions occurring with the EDCA access method, the appropriate
1046 // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
1047 // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
1048 // (Sec. 10.22.2.11.1 of 802.11-2016).
1049 // We do not prepare the PSDU that the AC losing the internal collision would have
1050 // sent. As an approximation, we consider the frame peeked from the queues of the AC.
1051 Ptr<QosTxop> qosTxop = (txop->IsQosTxop() ? StaticCast<QosTxop>(txop) : nullptr);
1052
1053 auto mpdu =
1054 (qosTxop ? qosTxop->PeekNextMpdu(m_linkId) : txop->GetWifiMacQueue()->Peek(m_linkId));
1055
1056 if (mpdu)
1057 {
1058 if (mpdu->GetHeader().HasData() && !mpdu->GetHeader().GetAddr1().IsGroup())
1059 {
1061 }
1062
1063 if (!mpdu->GetHeader().GetAddr1().IsGroup() &&
1064 !GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
1065 {
1066 NS_LOG_DEBUG("reset DCF");
1068 DequeueMpdu(mpdu);
1070 txop->ResetCw(m_linkId);
1071 }
1072 else
1073 {
1074 NS_LOG_DEBUG("Update CW");
1075 txop->UpdateFailedCw(m_linkId);
1076 }
1077 }
1078
1079 txop->Txop::NotifyChannelReleased(m_linkId);
1080}
1081
1082void
1084{
1085 NS_LOG_DEBUG("Switching channel. Cancelling MAC pending events");
1087 if (m_txTimer.IsRunning())
1088 {
1089 // we were transmitting something before channel switching. Since we will
1090 // not be able to receive the response, have the timer expire now, so that
1091 // we perform the actions required in case of missing response
1093 }
1095}
1096
1097void
1099{
1100 NS_LOG_DEBUG("Device in sleep mode. Cancelling MAC pending events");
1101 Reset();
1102}
1103
1104void
1106{
1107 NS_LOG_DEBUG("Device is switched off. Cancelling MAC pending events");
1108 Reset();
1109}
1110
1111void
1113 RxSignalInfo rxSignalInfo,
1114 WifiTxVector txVector,
1115 std::vector<bool> perMpduStatus)
1116{
1118 this << psdu << rxSignalInfo << txVector << perMpduStatus.size()
1119 << std::all_of(perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
1120
1121 if (!perMpduStatus.empty())
1122 {
1123 // for A-MPDUs, we get here only once
1124 PreProcessFrame(psdu, txVector);
1125 }
1126
1127 Mac48Address addr1 = psdu->GetAddr1();
1128
1129 if (addr1.IsGroup() || addr1 == m_self)
1130 {
1131 // receive broadcast frames or frames addressed to us only
1132 if (psdu->GetNMpdus() == 1)
1133 {
1134 // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
1135 // then it must contain a single value which must be true (i.e., the MPDU
1136 // has been correctly received)
1137 NS_ASSERT(perMpduStatus.empty() || (perMpduStatus.size() == 1 && perMpduStatus[0]));
1138 // Ack and CTS do not carry Addr2
1139 if (!psdu->GetHeader(0).IsAck() && !psdu->GetHeader(0).IsCts())
1140 {
1141 GetWifiRemoteStationManager()->ReportRxOk(psdu->GetHeader(0).GetAddr2(),
1142 rxSignalInfo,
1143 txVector);
1144 }
1145 ReceiveMpdu(*(psdu->begin()), rxSignalInfo, txVector, perMpduStatus.empty());
1146 }
1147 else
1148 {
1149 EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
1150 }
1151 }
1152 else if (m_promisc)
1153 {
1154 for (const auto& mpdu : *PeekPointer(psdu))
1155 {
1156 if (!mpdu->GetHeader().IsCtl())
1157 {
1158 m_rxMiddle->Receive(mpdu, m_linkId);
1159 }
1160 }
1161 }
1162
1163 if (!perMpduStatus.empty())
1164 {
1165 // for A-MPDUs, we get here only once
1166 PostProcessFrame(psdu, txVector);
1167 }
1168}
1169
1170void
1172{
1173 NS_LOG_FUNCTION(this << psdu << txVector);
1174}
1175
1176void
1178{
1179 NS_LOG_FUNCTION(this << psdu << txVector);
1180
1181 UpdateNav(psdu, txVector);
1182}
1183
1184void
1186{
1187 NS_LOG_FUNCTION(this << psdu << txVector);
1188
1189 if (!psdu->HasNav())
1190 {
1191 return;
1192 }
1193
1194 Time duration = psdu->GetDuration();
1195 NS_LOG_DEBUG("Duration/ID=" << duration);
1196
1197 if (psdu->GetAddr1() == m_self)
1198 {
1199 // When the received frame’s RA is equal to the STA’s own MAC address, the STA
1200 // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
1201 return;
1202 }
1203
1204 // For all other received frames the STA shall update its NAV when the received
1205 // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
1206 Time navEnd = Simulator::Now() + duration;
1207 if (navEnd > m_navEnd)
1208 {
1209 m_navEnd = navEnd;
1210 NS_LOG_DEBUG("Updated NAV=" << m_navEnd);
1211
1212 // A STA that used information from an RTS frame as the most recent basis to update
1213 // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
1214 // primitive is received from the PHY during a NAVTimeout period starting when the
1215 // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
1216 // the RTS frame. NAVTimeout period is equal to:
1217 // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
1218 // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
1219 // rate at which the RTS frame used for the most recent NAV update was received
1220 // (IEEE 802.11-2016 sec. 10.3.2.4)
1221 if (psdu->GetHeader(0).IsRts())
1222 {
1223 WifiTxVector ctsTxVector =
1224 GetWifiRemoteStationManager()->GetCtsTxVector(psdu->GetAddr2(), txVector.GetMode());
1225 Time navResetDelay =
1226 2 * m_phy->GetSifs() +
1231 }
1232 }
1233 NS_LOG_DEBUG("Current NAV=" << m_navEnd);
1234
1236}
1237
1238void
1240{
1241 NS_LOG_FUNCTION(this);
1244}
1245
1246bool
1248{
1249 return m_navEnd <= Simulator::Now();
1250}
1251
1252void
1254 RxSignalInfo rxSignalInfo,
1255 const WifiTxVector& txVector,
1256 bool inAmpdu)
1257{
1258 NS_LOG_FUNCTION(this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1259 // The received MPDU is either broadcast or addressed to this station
1260 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
1261
1262 double rxSnr = rxSignalInfo.snr;
1263 const WifiMacHeader& hdr = mpdu->GetHeader();
1264
1265 if (hdr.IsCtl())
1266 {
1267 if (hdr.IsRts())
1268 {
1269 NS_ABORT_MSG_IF(inAmpdu, "Received RTS as part of an A-MPDU");
1270
1271 // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1272 // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1273 // - Otherwise, the STA shall not respond with a CTS frame
1274 // (IEEE 802.11-2016 sec. 10.3.2.7)
1275 if (VirtualCsMediumIdle())
1276 {
1277 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", schedule CTS");
1280 this,
1281 hdr,
1282 txVector.GetMode(),
1283 rxSnr);
1284 }
1285 else
1286 {
1287 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", cannot schedule CTS");
1288 }
1289 }
1290 else if (hdr.IsCts() && m_txTimer.IsRunning() &&
1292 {
1293 NS_ABORT_MSG_IF(inAmpdu, "Received CTS as part of an A-MPDU");
1294 NS_ASSERT(hdr.GetAddr1() == m_self);
1295
1296 Mac48Address sender = m_mpdu->GetHeader().GetAddr1();
1297 NS_LOG_DEBUG("Received CTS from=" << sender);
1298
1299 SnrTag tag;
1300 mpdu->GetPacket()->PeekPacketTag(tag);
1301 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
1303 rxSnr,
1304 txVector.GetMode(),
1305 tag.Get());
1306
1307 m_txTimer.Cancel();
1310 }
1311 else if (hdr.IsAck() && m_mpdu && m_txTimer.IsRunning() &&
1313 {
1314 NS_ASSERT(hdr.GetAddr1() == m_self);
1315 SnrTag tag;
1316 mpdu->GetPacket()->PeekPacketTag(tag);
1317 ReceivedNormalAck(m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get());
1318 m_mpdu = nullptr;
1319 }
1320 }
1321 else if (hdr.IsMgt())
1322 {
1323 NS_ABORT_MSG_IF(inAmpdu, "Received management frame as part of an A-MPDU");
1324
1325 if (hdr.IsBeacon() || hdr.IsProbeResp())
1326 {
1327 // Apply SNR tag for beacon quality measurements
1328 SnrTag tag;
1329 tag.Set(rxSnr);
1330 Ptr<Packet> packet = mpdu->GetPacket()->Copy();
1331 packet->AddPacketTag(tag);
1332 mpdu = Create<WifiMpdu>(packet, hdr);
1333 }
1334
1335 if (hdr.GetAddr1() == m_self)
1336 {
1337 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1338 << ", schedule ACK");
1341 this,
1342 hdr,
1343 txVector,
1344 rxSnr);
1345 }
1346
1347 m_rxMiddle->Receive(mpdu, m_linkId);
1348 }
1349 else if (hdr.IsData() && !hdr.IsQosData())
1350 {
1351 if (hdr.GetAddr1() == m_self)
1352 {
1353 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1354 << ", schedule ACK");
1357 this,
1358 hdr,
1359 txVector,
1360 rxSnr);
1361 }
1362
1363 m_rxMiddle->Receive(mpdu, m_linkId);
1364 }
1365}
1366
1367void
1369 const WifiTxVector& txVector,
1370 const WifiTxVector& ackTxVector,
1371 const RxSignalInfo& rxInfo,
1372 double snr)
1373{
1374 Mac48Address sender = mpdu->GetHeader().GetAddr1();
1375 NS_LOG_DEBUG("Received ACK from=" << sender);
1376
1378
1379 // When fragmentation is used, only update manager when the last fragment is acknowledged
1380 if (!mpdu->GetHeader().IsMoreFragments())
1381 {
1382 GetWifiRemoteStationManager()->ReportRxOk(sender, rxInfo, ackTxVector);
1384 rxInfo.snr,
1385 ackTxVector.GetMode(),
1386 snr,
1387 txVector);
1388 }
1389 // cancel the timer
1390 m_txTimer.Cancel();
1392
1393 // The CW shall be reset to aCWmin after every successful attempt to transmit
1394 // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1396
1397 if (mpdu->GetHeader().IsMoreFragments())
1398 {
1399 // replace the current fragment with the next one
1400 m_dcf->GetWifiMacQueue()->Replace(mpdu, GetNextFragment());
1401 m_moreFragments = true;
1402 }
1403 else
1404 {
1405 // the MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1406 DequeueMpdu(mpdu);
1407 }
1408
1410}
1411
1412void
1414{
1415 NS_LOG_FUNCTION(this << *mpdu);
1416
1417 // inform the MAC that the transmission was successful
1419 {
1420 m_ackedMpduCallback(mpdu);
1421 }
1422}
1423
1424void
1426 const RxSignalInfo& rxSignalInfo,
1427 const WifiTxVector& txVector,
1428 const std::vector<bool>& perMpduStatus)
1429{
1430 NS_ASSERT_MSG(false, "A non-QoS station should not receive an A-MPDU");
1431}
1432
1433} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
void NotifyAckTimeoutResetNow()
Notify that ack timer has reset.
void NotifyAckTimeoutStartNow(Time duration)
Notify that ack timer has started for the given duration.
void NotifyCtsTimeoutStartNow(Time duration)
Notify that CTS timer has started for the given duration.
void NotifyCtsTimeoutResetNow()
Notify that CTS timer has reset.
void NotifyNavResetNow(Time duration)
void NotifyNavStartNow(Time duration)
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
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.
uint16_t m_allowedWidth
the allowed width in MHz for the current transmission
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
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.
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 CalculateProtectionTime(WifiProtection *protection) const
Calculate the time required to protect a frame according to the given protection method.
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.
bool m_moreFragments
true if a fragment has to be sent after a SIFS
void SetPromisc()
Enable promiscuous mode.
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 bool StartTransmission(Ptr< Txop > dcf, uint16_t allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
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
Definition: mac48-address.h:46
bool IsGroup() const
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:311
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:339
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
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:238
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:606
Introspection did not find any typical Config paths.
Definition: snr-tag.h:35
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:84
double Get() const
Return the SNR value.
Definition: snr-tag.cc:90
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:350
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:286
@ US
microsecond
Definition: nstime.h:118
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
Definition: nstime.h:341
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:296
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:216
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:287
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:572
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
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).
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.
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.
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:580
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:425
virtual Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
Definition: wifi-mac.cc:543
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:910
represent a single transmission mode
Definition: wifi-mode.h:51
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:1709
Time GetSlot() const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:795
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:783
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1496
Ptr< WifiPhyStateHelper > GetState() const
Return the WifiPhyStateHelper of this PHY.
Definition: wifi-phy.cc:445
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1005
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:451
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1489
void ReportDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
WifiTxVector GetAckTxVector(Mac48Address to, const WifiTxVector &dataTxVector) const
Return a TXVECTOR for the Ack frame given the destination and the mode of the Data used by the sender...
void ReportFinalDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked after calling ReportDataFailed if NeedRetransmission returns false.
void ReportRtsOk(const WifiMacHeader &header, double ctsSnr, WifiMode ctsMode, double rtsSnr)
Should be invoked whenever we receive the CTS associated to an RTS we just sent.
void ReportRxOk(Mac48Address address, RxSignalInfo rxSignalInfo, WifiTxVector txVector)
void ReportFinalRtsFailed(const WifiMacHeader &header)
Should be invoked after calling ReportRtsFailed if NeedRetransmission returns false.
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender.
WifiTxVector GetDataTxVector(const WifiMacHeader &header, uint16_t allowedWidth)
void ReportDataOk(Ptr< const WifiMpdu > mpdu, double ackSnr, WifiMode ackMode, double dataSnr, WifiTxVector dataTxVector)
Should be invoked whenever we receive the ACK associated to a data packet we just sent.
void ReportRtsFailed(const WifiMacHeader &header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
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
Time m_txDuration
TX duration of the frame.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void AddMpdu(Ptr< const WifiMpdu > mpdu)
Record that an MPDU is being added to the current frame.
void Clear()
Reset the TX parameters.
This class is used to handle the timer that a station starts when transmitting a frame that solicits ...
Definition: wifi-tx-timer.h:49
bool IsRunning() const
Return true if the timer is running.
void Cancel()
Cancel the timer.
void Set(Reason reason, const Time &delay, MEM mem_ptr, OBJ obj, Args... args)
This method is called when a frame soliciting a response is transmitted.
Reason 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.
#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:66
#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:86
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:745
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:46
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
@ STA
Definition: wifi-mac.h:63
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition: wifi-mac.h:78
@ WIFI_PM_SWITCHING_TO_ACTIVE
Definition: sta-wifi-mac.h:96
@ WIFI_PM_POWERSAVE
Definition: sta-wifi-mac.h:95
@ WIFI_PM_SWITCHING_TO_PS
Definition: sta-wifi-mac.h:94
@ WIFI_PM_ACTIVE
Definition: sta-wifi-mac.h:93
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
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:702
uint32_t GetRtsSize()
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:103
@ WIFI_MAC_CTL_RTS
@ WIFI_MAC_CTL_CTS
@ WIFI_MAC_CTL_ACK
uint32_t GetAckSize()
Return the total Ack size (including FCS trailer).
Definition: wifi-utils.cc:58
uint32_t GetCtsSize()
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:111
ns3::Time timeout
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
double snr
SNR in linear scale.
Definition: phy-entity.h:71
WifiAcknowledgment is an abstract base struct.
Time acknowledgmentTime
time required by the acknowledgment method
const Method method
acknowledgment method
WifiCtsToSelfProtection specifies that CTS-to-self protection method is used.
WifiTxVector ctsTxVector
CTS TXVECTOR.
WifiNormalAck specifies that acknowledgment via Normal Ack is required.
WifiTxVector ackTxVector
Ack TXVECTOR.
WifiProtection is an abstract base struct.
Time protectionTime
time required by the protection method
const Method method
protection method
WifiRtsCtsProtection specifies that RTS/CTS protection method is used.
WifiTxVector ctsTxVector
CTS TXVECTOR.
WifiTxVector rtsTxVector
RTS TXVECTOR.