A Discrete-Event Network Simulator
API
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
23#include "snr-tag.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 if (m_phy)
99 {
101 "PhyRxPayloadBegin",
103 }
104 m_phy = nullptr;
106}
107
108void
110{
111 NS_LOG_FUNCTION(this << protectionManager);
112 m_protectionManager = protectionManager;
113}
114
117{
118 return m_protectionManager;
119}
120
121void
123{
124 NS_LOG_FUNCTION(this << ackManager);
125 m_ackManager = ackManager;
126}
127
130{
131 return m_ackManager;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this << +linkId);
138 m_linkId = linkId;
139}
140
141void
143{
144 NS_LOG_FUNCTION(this << mac);
145 m_mac = mac;
146}
147
148void
150{
151 NS_LOG_FUNCTION(this << txMiddle);
152 m_txMiddle = txMiddle;
153}
154
155void
157{
158 NS_LOG_FUNCTION(this << rxMiddle);
159 m_rxMiddle = rxMiddle;
160}
161
162void
164{
165 NS_LOG_FUNCTION(this << channelAccessManager);
166 m_channelAccessManager = channelAccessManager;
167}
168
171{
172 return m_mac->GetWifiRemoteStationManager(m_linkId);
173}
174
175void
177{
178 NS_LOG_FUNCTION(this << phy);
179 m_phy = phy;
180 m_phy->TraceConnectWithoutContext("PhyRxPayloadBegin",
183}
184
185void
187{
188 NS_LOG_FUNCTION(this);
189 if (m_phy)
190 {
192 "PhyRxPayloadBegin",
198 std::vector<bool>>());
199 m_phy = nullptr;
200 }
201}
202
203void
205{
206 NS_LOG_FUNCTION(this << address);
207 // For APs, the BSSID is the MAC address. For STAs, the BSSID will be overwritten
208 // when receiving Beacon frames or Probe Response frames
210 m_self = address;
211}
212
215{
216 return m_self;
217}
218
219void
221{
222 NS_LOG_FUNCTION(this << bssid);
223 m_bssid = bssid;
224}
225
228{
229 return m_bssid;
230}
231
232void
234{
235 NS_LOG_FUNCTION(this << &callback);
236 m_droppedMpduCallback = callback;
237}
238
239void
241{
242 NS_LOG_FUNCTION(this << &callback);
243 m_ackedMpduCallback = callback;
244}
245
246void
248{
249 m_promisc = true;
250}
251
252bool
254{
255 return m_promisc;
256}
257
258const WifiTxTimer&
260{
261 return m_txTimer;
262}
263
264void
266{
268 {
270 }
271}
272
273void
275{
276 NS_LOG_FUNCTION(this << "PSDU reception started for " << psduDuration.As(Time::US)
277 << " (txVector: " << txVector << ")");
278
280 "The TX timer and the NAV reset event cannot be both running");
281
282 // No need to reschedule timeouts if PSDU duration is null. In this case,
283 // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered)
284 // and CCA will take over
285 if (m_txTimer.IsRunning() && psduDuration.IsStrictlyPositive())
286 {
287 // we are waiting for a response and something arrived
288 NS_LOG_DEBUG("Rescheduling timeout event");
290 // PHY has switched to RX, so we can reset the ack timeout
292 }
293
295 {
297 }
298}
299
300bool
302{
303 NS_LOG_FUNCTION(this << dcf << allowedWidth);
304
306 if (m_txTimer.IsRunning())
307 {
309 }
310 m_dcf = dcf;
311 m_allowedWidth = allowedWidth;
312
313 Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue();
314
315 // Even though channel access is requested when the queue is not empty, at
316 // the time channel access is granted the lifetime of the packet might be
317 // expired and the queue might be empty.
318 queue->WipeAllExpiredMpdus();
319
320 Ptr<WifiMpdu> mpdu = queue->Peek(m_linkId);
321
322 if (!mpdu)
323 {
324 NS_LOG_DEBUG("Queue empty");
326 m_dcf = nullptr;
327 return false;
328 }
329
331
332 NS_ASSERT(mpdu->GetHeader().IsData() || mpdu->GetHeader().IsMgt());
333
334 // assign a sequence number if this is not a fragment nor a retransmission
335 if (!mpdu->IsFragment() && !mpdu->GetHeader().IsRetry())
336 {
337 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&mpdu->GetHeader());
338 mpdu->GetHeader().SetSequenceNumber(sequence);
339 }
340
341 NS_LOG_DEBUG("MPDU payload size=" << mpdu->GetPacketSize()
342 << ", to=" << mpdu->GetHeader().GetAddr1()
343 << ", seq=" << mpdu->GetHeader().GetSequenceControl());
344
345 // check if the MSDU needs to be fragmented
346 mpdu = GetFirstFragmentIfNeeded(mpdu);
347
350 WifiTxParameters txParams;
351 txParams.m_txVector =
353 txParams.m_protection = m_protectionManager->TryAddMpdu(mpdu, txParams);
354 txParams.m_acknowledgment = m_ackManager->TryAddMpdu(mpdu, txParams);
355 txParams.AddMpdu(mpdu);
356 UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
357
358 SendMpduWithProtection(mpdu, txParams);
359
360 return true;
361}
362
365{
366 NS_LOG_FUNCTION(this << *mpdu);
367
368 if (mpdu->IsFragment())
369 {
370 // a fragment cannot be further fragmented
372 }
373 else if (GetWifiRemoteStationManager()->NeedFragmentation(mpdu))
374 {
375 NS_LOG_DEBUG("Fragmenting the MSDU");
376 m_fragmentedPacket = mpdu->GetPacket()->Copy();
377 // create the first fragment
379 0,
380 GetWifiRemoteStationManager()->GetFragmentSize(mpdu, 0));
381 // enqueue the first fragment
382 Ptr<WifiMpdu> item = Create<WifiMpdu>(fragment, mpdu->GetHeader());
383 item->GetHeader().SetMoreFragments();
384 m_mac->GetTxopQueue(mpdu->GetQueueAc())->Replace(mpdu, item);
385 return item;
386 }
387 return mpdu;
388}
389
390void
392{
393 NS_LOG_FUNCTION(this << *mpdu << &txParams);
394
395 m_mpdu = mpdu;
396 m_txParams = std::move(txParams);
397
398 // If protection is required, the MPDU must be stored in some queue because
399 // it is not put back in a queue if the RTS/CTS exchange fails
401 m_mpdu->GetHeader().IsCtl() || m_mpdu->IsQueued());
402
403 // Make sure that the acknowledgment time has been computed, so that SendRts()
404 // and SendCtsToSelf() can reuse this value.
406
407 if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min())
408 {
410 }
411
412 // Set QoS Ack policy if this is a QoS data frame
414
415 switch (m_txParams.m_protection->method)
416 {
419 break;
422 break;
424 SendMpdu();
425 break;
426 default:
427 NS_ABORT_MSG("Unknown protection type");
428 }
429}
430
431void
433{
434 NS_LOG_FUNCTION(this);
435
438 m_phy->GetPhyBand());
439
441
443 {
445
446 if (!m_mpdu->GetHeader().IsQosData() ||
447 m_mpdu->GetHeader().GetQosAckPolicy() == WifiMacHeader::NO_ACK)
448 {
449 // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
451 }
452 }
454 {
455 m_mpdu->GetHeader().SetDuration(
456 GetFrameDurationId(m_mpdu->GetHeader(),
460
461 // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
462 // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
463 // aRxPHYStartDelay equals the time to transmit the PHY header.
464 WifiNormalAck* normalAcknowledgment =
465 static_cast<WifiNormalAck*>(m_txParams.m_acknowledgment.get());
466
467 Time timeout =
468 txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
472 timeout,
474 this,
475 m_mpdu,
478 }
479 else
480 {
481 NS_ABORT_MSG("Unable to handle the selected acknowledgment method ("
482 << m_txParams.m_acknowledgment.get() << ")");
483 }
484
485 // transmit the MPDU
487
489 {
490 // we are done with frames that do not require acknowledgment
491 m_mpdu = nullptr;
492 }
493}
494
495void
497{
498 NS_LOG_FUNCTION(this << *mpdu << txVector);
499
500 m_phy->Send(Create<WifiPsdu>(mpdu, false), txVector);
501}
502
503void
505{
506 NS_LOG_DEBUG(this << *mpdu);
507
508 if (mpdu->IsQueued())
509 {
510 m_mac->GetTxopQueue(mpdu->GetQueueAc())->DequeueIfQueued({mpdu});
511 }
512}
513
516{
517 return mpdu->GetSize();
518}
519
520void
522{
523 NS_LOG_FUNCTION(this << protection);
524 NS_ASSERT(protection);
525
526 if (protection->method == WifiProtection::NONE)
527 {
528 protection->protectionTime = Seconds(0);
529 }
530 else if (protection->method == WifiProtection::RTS_CTS)
531 {
532 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*>(protection);
533 rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration(GetRtsSize(),
534 rtsCtsProtection->rtsTxVector,
535 m_phy->GetPhyBand()) +
537 rtsCtsProtection->ctsTxVector,
538 m_phy->GetPhyBand()) +
539 2 * m_phy->GetSifs();
540 }
541 else if (protection->method == WifiProtection::CTS_TO_SELF)
542 {
543 WifiCtsToSelfProtection* ctsToSelfProtection =
544 static_cast<WifiCtsToSelfProtection*>(protection);
545 ctsToSelfProtection->protectionTime =
547 ctsToSelfProtection->ctsTxVector,
548 m_phy->GetPhyBand()) +
549 m_phy->GetSifs();
550 }
551}
552
553void
555{
556 NS_LOG_FUNCTION(this << acknowledgment);
557 NS_ASSERT(acknowledgment);
558
559 if (acknowledgment->method == WifiAcknowledgment::NONE)
560 {
561 acknowledgment->acknowledgmentTime = Seconds(0);
562 }
563 else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
564 {
565 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*>(acknowledgment);
566 normalAcknowledgment->acknowledgmentTime =
568 normalAcknowledgment->ackTxVector,
569 m_phy->GetPhyBand());
570 }
571}
572
573Time
575 Mac48Address receiver,
576 const WifiTxParameters& txParams) const
577{
578 return m_phy->CalculateTxDuration(ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand());
579}
580
581void
583{
584 txParams.m_txDuration = GetTxDuration(txParams.GetSize(receiver), receiver, txParams);
585}
586
587Time
589 uint32_t size,
590 const WifiTxParameters& txParams,
591 Ptr<Packet> fragmentedPacket) const
592{
593 NS_LOG_FUNCTION(this << header << size << &txParams << fragmentedPacket);
594
595 NS_ASSERT(txParams.m_acknowledgment &&
596 txParams.m_acknowledgment->acknowledgmentTime != Time::Min());
597 Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
598
599 // if the current frame is a fragment followed by another fragment, we have to
600 // update the Duration/ID to cover the next fragment and the corresponding Ack
601 if (header.IsMoreFragments())
602 {
603 uint32_t payloadSize = size - header.GetSize() - WIFI_MAC_FCS_LENGTH;
604 uint32_t nextFragmentOffset = (header.GetFragmentNumber() + 1) * payloadSize;
605 uint32_t nextFragmentSize =
606 std::min(fragmentedPacket->GetSize() - nextFragmentOffset, payloadSize);
607 WifiTxVector ackTxVector =
609
610 durationId +=
611 2 * m_phy->GetSifs() +
613 m_phy->CalculateTxDuration(nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand());
614 }
615 return durationId;
616}
617
618Time
620 Time txDuration,
621 Time response) const
622{
623 NS_LOG_FUNCTION(this << rtsTxVector << txDuration << response);
624
625 WifiTxVector ctsTxVector;
626 ctsTxVector = GetWifiRemoteStationManager()->GetCtsTxVector(m_self, rtsTxVector.GetMode());
627
628 return m_phy->GetSifs() +
629 m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()) /* CTS */
630 + m_phy->GetSifs() + txDuration + response;
631}
632
633void
635{
636 NS_LOG_FUNCTION(this << &txParams);
637
638 NS_ASSERT(txParams.GetPsduInfoMap().size() == 1);
639 Mac48Address receiver = txParams.GetPsduInfoMap().begin()->first;
640
641 WifiMacHeader rts;
643 rts.SetDsNotFrom();
644 rts.SetDsNotTo();
645 rts.SetNoRetry();
646 rts.SetNoMoreFragments();
647 rts.SetAddr1(receiver);
648 rts.SetAddr2(m_self);
649
650 NS_ASSERT(txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
651 WifiRtsCtsProtection* rtsCtsProtection =
652 static_cast<WifiRtsCtsProtection*>(txParams.m_protection.get());
653
654 NS_ASSERT(txParams.m_txDuration != Time::Min());
655 rts.SetDuration(GetRtsDurationId(rtsCtsProtection->rtsTxVector,
656 txParams.m_txDuration,
657 txParams.m_acknowledgment->acknowledgmentTime));
658 Ptr<WifiMpdu> mpdu = Create<WifiMpdu>(Create<Packet>(), rts);
659
660 // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
661 // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
662 // aRxPHYStartDelay equals the time to transmit the PHY header.
664 rtsCtsProtection->rtsTxVector,
665 m_phy->GetPhyBand()) +
666 m_phy->GetSifs() + m_phy->GetSlot() +
670 timeout,
672 this,
673 mpdu,
674 rtsCtsProtection->rtsTxVector);
676
677 ForwardMpduDown(mpdu, rtsCtsProtection->rtsTxVector);
678}
679
680void
682 WifiTxVector& ctsTxVector,
683 double rtsSnr)
684{
685 NS_LOG_FUNCTION(this << rtsHdr << ctsTxVector << rtsSnr);
686
687 WifiMacHeader cts;
689 cts.SetDsNotFrom();
690 cts.SetDsNotTo();
691 cts.SetNoMoreFragments();
692 cts.SetNoRetry();
693 cts.SetAddr1(rtsHdr.GetAddr2());
694 Time duration = rtsHdr.GetDuration() - m_phy->GetSifs() -
696 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
697 if (duration.IsStrictlyNegative())
698 {
699 duration = Seconds(0);
700 }
701 cts.SetDuration(duration);
702
703 Ptr<Packet> packet = Create<Packet>();
704
705 SnrTag tag;
706 tag.Set(rtsSnr);
707 packet->AddPacketTag(tag);
708
709 // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
710 ForwardMpduDown(Create<WifiMpdu>(packet, cts), ctsTxVector);
711}
712
713void
715 WifiMode rtsTxMode,
716 double rtsSnr)
717{
718 NS_LOG_FUNCTION(this << rtsHdr << rtsTxMode << rtsSnr);
719
720 WifiTxVector ctsTxVector =
722 DoSendCtsAfterRts(rtsHdr, ctsTxVector, rtsSnr);
723}
724
725Time
727 Time txDuration,
728 Time response) const
729{
730 NS_LOG_FUNCTION(this << ctsTxVector << txDuration << response);
731
732 return m_phy->GetSifs() + txDuration + response;
733}
734
735void
737{
738 NS_LOG_FUNCTION(this << &txParams);
739
740 WifiMacHeader cts;
742 cts.SetDsNotFrom();
743 cts.SetDsNotTo();
744 cts.SetNoMoreFragments();
745 cts.SetNoRetry();
746 cts.SetAddr1(m_self);
747
748 NS_ASSERT(txParams.m_protection &&
749 txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
750 WifiCtsToSelfProtection* ctsToSelfProtection =
751 static_cast<WifiCtsToSelfProtection*>(txParams.m_protection.get());
752
753 NS_ASSERT(txParams.m_txDuration != Time::Min());
754 cts.SetDuration(GetCtsToSelfDurationId(ctsToSelfProtection->ctsTxVector,
755 txParams.m_txDuration,
756 txParams.m_acknowledgment->acknowledgmentTime));
757
758 ForwardMpduDown(Create<WifiMpdu>(Create<Packet>(), cts), ctsToSelfProtection->ctsTxVector);
759
760 Time ctsDuration = m_phy->CalculateTxDuration(GetCtsSize(),
761 ctsToSelfProtection->ctsTxVector,
762 m_phy->GetPhyBand());
764}
765
766void
768 const WifiTxVector& dataTxVector,
769 double dataSnr)
770{
771 NS_LOG_FUNCTION(this << hdr << dataTxVector << dataSnr);
772
773 WifiTxVector ackTxVector =
775 WifiMacHeader ack;
777 ack.SetDsNotFrom();
778 ack.SetDsNotTo();
779 ack.SetNoRetry();
780 ack.SetNoMoreFragments();
781 ack.SetAddr1(hdr.GetAddr2());
782 // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
783 // minus the time to transmit the Ack frame and its SIFS interval
784 Time duration = hdr.GetDuration() - m_phy->GetSifs() -
786 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
787 if (duration.IsStrictlyNegative())
788 {
789 duration = Seconds(0);
790 }
791 ack.SetDuration(duration);
792
793 Ptr<Packet> packet = Create<Packet>();
794
795 SnrTag tag;
796 tag.Set(dataSnr);
797 packet->AddPacketTag(tag);
798
799 ForwardMpduDown(Create<WifiMpdu>(packet, ack), ackTxVector);
800}
801
804{
805 NS_LOG_FUNCTION(this);
806 NS_ASSERT(m_mpdu->GetHeader().IsMoreFragments());
807
808 WifiMacHeader& hdr = m_mpdu->GetHeader();
810
811 uint32_t startOffset = hdr.GetFragmentNumber() * m_mpdu->GetPacketSize();
812 uint32_t size = m_fragmentedPacket->GetSize() - startOffset;
813
814 if (size > m_mpdu->GetPacketSize())
815 {
816 // this is not the last fragment
817 size = m_mpdu->GetPacketSize();
818 hdr.SetMoreFragments();
819 }
820 else
821 {
822 hdr.SetNoMoreFragments();
823 }
824
825 return Create<WifiMpdu>(m_fragmentedPacket->CreateFragment(startOffset, size), hdr);
826}
827
828void
830{
831 NS_LOG_FUNCTION(this);
832
833 // Upon a transmission success, a non-QoS station transmits the next fragment,
834 // if any, or releases the channel, otherwise
835 if (m_moreFragments)
836 {
837 NS_LOG_DEBUG("Schedule transmission of next fragment in a SIFS");
840 this,
841 m_dcf,
843 m_moreFragments = false;
844 }
845 else
846 {
848 m_dcf = nullptr;
849 }
850}
851
852void
854{
855 NS_LOG_FUNCTION(this);
856 // A non-QoS station always releases the channel upon a transmission failure
858 m_dcf = nullptr;
859}
860
861void
863{
864 NS_LOG_FUNCTION(this << *mpdu << txVector);
865
867
868 if (!GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
869 {
870 NS_LOG_DEBUG("Missed Ack, discard MPDU");
872 // Dequeue the MPDU if it is stored in a queue
873 DequeueMpdu(mpdu);
876 }
877 else
878 {
879 NS_LOG_DEBUG("Missed Ack, retransmit MPDU");
880 mpdu->GetHeader().SetRetry();
883 }
884
885 m_mpdu = nullptr;
887}
888
889void
891{
892 NS_LOG_FUNCTION(this << *mpdu);
893}
894
895void
897{
898 NS_LOG_FUNCTION(this << *rts << txVector);
899
900 DoCtsTimeout(Create<WifiPsdu>(m_mpdu, true));
901 m_mpdu = nullptr;
902}
903
904void
906{
907 NS_LOG_FUNCTION(this << *psdu);
908
910
911 if (!GetWifiRemoteStationManager()->NeedRetransmission(*psdu->begin()))
912 {
913 NS_LOG_DEBUG("Missed CTS, discard MPDU(s)");
915 for (const auto& mpdu : *PeekPointer(psdu))
916 {
917 // Dequeue the MPDU if it is stored in a queue
918 DequeueMpdu(mpdu);
920 }
922 }
923 else
924 {
925 NS_LOG_DEBUG("Missed CTS, retransmit MPDU(s)");
927 }
928 // Make the sequence numbers of the MPDUs available again if the MPDUs have never
929 // been transmitted, both in case the MPDUs have been discarded and in case the
930 // MPDUs have to be transmitted (because a new sequence number is assigned to
931 // MPDUs that have never been transmitted and are selected for transmission)
932 for (const auto& mpdu : *PeekPointer(psdu))
933 {
935 }
937}
938
939void
941{
942 NS_LOG_FUNCTION(this << *mpdu);
943
944 // the MPDU should be still in the DCF queue, unless it expired.
945 // If the MPDU has never been transmitted, it will be assigned a sequence
946 // number again the next time we try to transmit it. Therefore, we need to
947 // make its sequence number available again
948 if (!mpdu->GetHeader().IsRetry())
949 {
950 m_txMiddle->SetSequenceNumberFor(&mpdu->GetHeader());
951 }
952}
953
954void
956{
957 NS_LOG_FUNCTION(this);
958
959 // For internal collisions occurring with the EDCA access method, the appropriate
960 // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
961 // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
962 // (Sec. 10.22.2.11.1 of 802.11-2016).
963 // We do not prepare the PSDU that the AC losing the internal collision would have
964 // sent. As an approximation, we consider the frame peeked from the queues of the AC.
965 Ptr<QosTxop> qosTxop = (txop->IsQosTxop() ? StaticCast<QosTxop>(txop) : nullptr);
966
967 auto mpdu =
968 (qosTxop ? qosTxop->PeekNextMpdu(m_linkId) : txop->GetWifiMacQueue()->Peek(m_linkId));
969
970 if (mpdu)
971 {
972 if (mpdu->GetHeader().HasData() && !mpdu->GetHeader().GetAddr1().IsGroup())
973 {
975 }
976
977 if (!mpdu->GetHeader().GetAddr1().IsGroup() &&
978 !GetWifiRemoteStationManager()->NeedRetransmission(mpdu))
979 {
980 NS_LOG_DEBUG("reset DCF");
982 DequeueMpdu(mpdu);
984 txop->ResetCw(m_linkId);
985 }
986 else
987 {
988 NS_LOG_DEBUG("Update CW");
990 }
991 }
992
993 txop->Txop::NotifyChannelReleased(m_linkId);
994}
995
996void
998{
999 NS_LOG_DEBUG("Switching channel. Cancelling MAC pending events");
1001 if (m_txTimer.IsRunning())
1002 {
1003 // we were transmitting something before channel switching. Since we will
1004 // not be able to receive the response, have the timer expire now, so that
1005 // we perform the actions required in case of missing response
1007 }
1009}
1010
1011void
1013{
1014 NS_LOG_DEBUG("Device in sleep mode. Cancelling MAC pending events");
1015 Reset();
1016}
1017
1018void
1020{
1021 NS_LOG_DEBUG("Device is switched off. Cancelling MAC pending events");
1022 Reset();
1023}
1024
1025void
1027 RxSignalInfo rxSignalInfo,
1028 WifiTxVector txVector,
1029 std::vector<bool> perMpduStatus)
1030{
1032 this << psdu << rxSignalInfo << txVector << perMpduStatus.size()
1033 << std::all_of(perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
1034
1035 if (!perMpduStatus.empty())
1036 {
1037 // for A-MPDUs, we get here only once
1038 PreProcessFrame(psdu, txVector);
1039 }
1040
1041 // ignore unicast frames that are not addressed to us
1042 Mac48Address addr1 = psdu->GetAddr1();
1043 if (!addr1.IsGroup() && addr1 != m_self)
1044 {
1045 if (m_promisc && psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsData())
1046 {
1047 m_rxMiddle->Receive(*psdu->begin(), m_linkId);
1048 }
1049 return;
1050 }
1051
1052 if (psdu->GetNMpdus() == 1)
1053 {
1054 // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
1055 // then it must contain a single value which must be true (i.e., the MPDU
1056 // has been correctly received)
1057 NS_ASSERT(perMpduStatus.empty() || (perMpduStatus.size() == 1 && perMpduStatus[0]));
1058 // Ack and CTS do not carry Addr2
1059 if (!psdu->GetHeader(0).IsAck() && !psdu->GetHeader(0).IsCts())
1060 {
1062 rxSignalInfo,
1063 txVector);
1064 }
1065 ReceiveMpdu(*(psdu->begin()), rxSignalInfo, txVector, perMpduStatus.empty());
1066 }
1067 else
1068 {
1069 EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
1070 }
1071}
1072
1073void
1075{
1076 NS_LOG_FUNCTION(this << psdu << txVector);
1077
1078 UpdateNav(psdu, txVector);
1079}
1080
1081void
1083{
1084 NS_LOG_FUNCTION(this << psdu << txVector);
1085
1086 if (psdu->GetHeader(0).GetRawDuration() > 32767)
1087 {
1088 // When the contents of a received Duration/ID field, treated as an unsigned
1089 // integer, are greater than 32 768, the contents are interpreted as appropriate
1090 // for the frame type and subtype or ignored if the receiving MAC entity does
1091 // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
1092 // sec. 10.27.3)
1093 return;
1094 }
1095
1096 Time duration = psdu->GetDuration();
1097 NS_LOG_DEBUG("Duration/ID=" << duration);
1098
1099 if (psdu->GetAddr1() == m_self)
1100 {
1101 // When the received frame’s RA is equal to the STA’s own MAC address, the STA
1102 // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
1103 return;
1104 }
1105
1106 // For all other received frames the STA shall update its NAV when the received
1107 // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
1108 Time navEnd = Simulator::Now() + duration;
1109 if (navEnd > m_navEnd)
1110 {
1111 m_navEnd = navEnd;
1112 NS_LOG_DEBUG("Updated NAV=" << m_navEnd);
1113
1114 // A STA that used information from an RTS frame as the most recent basis to update
1115 // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
1116 // primitive is received from the PHY during a NAVTimeout period starting when the
1117 // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
1118 // the RTS frame. NAVTimeout period is equal to:
1119 // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
1120 // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
1121 // rate at which the RTS frame used for the most recent NAV update was received
1122 // (IEEE 802.11-2016 sec. 10.3.2.4)
1123 if (psdu->GetHeader(0).IsRts())
1124 {
1125 Time navResetDelay =
1126 2 * m_phy->GetSifs() +
1131 }
1132 }
1133 NS_LOG_DEBUG("Current NAV=" << m_navEnd);
1134
1136}
1137
1138void
1140{
1141 NS_LOG_FUNCTION(this);
1144}
1145
1146void
1148 RxSignalInfo rxSignalInfo,
1149 const WifiTxVector& txVector,
1150 bool inAmpdu)
1151{
1152 NS_LOG_FUNCTION(this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1153 // The received MPDU is either broadcast or addressed to this station
1154 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
1155
1156 double rxSnr = rxSignalInfo.snr;
1157 const WifiMacHeader& hdr = mpdu->GetHeader();
1158
1159 if (hdr.IsCtl())
1160 {
1161 if (hdr.IsRts())
1162 {
1163 NS_ABORT_MSG_IF(inAmpdu, "Received RTS as part of an A-MPDU");
1164
1165 // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1166 // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1167 // - Otherwise, the STA shall not respond with a CTS frame
1168 // (IEEE 802.11-2016 sec. 10.3.2.7)
1169 if (m_navEnd <= Simulator::Now())
1170 {
1171 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", schedule CTS");
1174 this,
1175 hdr,
1176 txVector.GetMode(),
1177 rxSnr);
1178 }
1179 else
1180 {
1181 NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", cannot schedule CTS");
1182 }
1183 }
1184 else if (hdr.IsCts() && m_txTimer.IsRunning() &&
1186 {
1187 NS_ABORT_MSG_IF(inAmpdu, "Received CTS as part of an A-MPDU");
1188 NS_ASSERT(hdr.GetAddr1() == m_self);
1189
1190 Mac48Address sender = m_mpdu->GetHeader().GetAddr1();
1191 NS_LOG_DEBUG("Received CTS from=" << sender);
1192
1193 SnrTag tag;
1194 mpdu->GetPacket()->PeekPacketTag(tag);
1195 GetWifiRemoteStationManager()->ReportRxOk(sender, rxSignalInfo, txVector);
1197 rxSnr,
1198 txVector.GetMode(),
1199 tag.Get());
1200
1201 m_txTimer.Cancel();
1204 }
1205 else if (hdr.IsAck() && m_mpdu && m_txTimer.IsRunning() &&
1207 {
1208 NS_ASSERT(hdr.GetAddr1() == m_self);
1209 SnrTag tag;
1210 mpdu->GetPacket()->PeekPacketTag(tag);
1211 ReceivedNormalAck(m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get());
1212 m_mpdu = nullptr;
1213 }
1214 }
1215 else if (hdr.IsMgt())
1216 {
1217 NS_ABORT_MSG_IF(inAmpdu, "Received management frame as part of an A-MPDU");
1218
1219 if (hdr.IsBeacon() || hdr.IsProbeResp())
1220 {
1221 // Apply SNR tag for beacon quality measurements
1222 SnrTag tag;
1223 tag.Set(rxSnr);
1224 Ptr<Packet> packet = mpdu->GetPacket()->Copy();
1225 packet->AddPacketTag(tag);
1226 mpdu = Create<WifiMpdu>(packet, hdr);
1227 }
1228
1229 if (hdr.GetAddr1() == m_self)
1230 {
1231 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1232 << ", schedule ACK");
1235 this,
1236 hdr,
1237 txVector,
1238 rxSnr);
1239 }
1240
1241 m_rxMiddle->Receive(mpdu, m_linkId);
1242 }
1243 else if (hdr.IsData() && !hdr.IsQosData())
1244 {
1245 if (hdr.GetAddr1() == m_self)
1246 {
1247 NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
1248 << ", schedule ACK");
1251 this,
1252 hdr,
1253 txVector,
1254 rxSnr);
1255 }
1256
1257 m_rxMiddle->Receive(mpdu, m_linkId);
1258 }
1259}
1260
1261void
1263 const WifiTxVector& txVector,
1264 const WifiTxVector& ackTxVector,
1265 const RxSignalInfo& rxInfo,
1266 double snr)
1267{
1268 Mac48Address sender = mpdu->GetHeader().GetAddr1();
1269 NS_LOG_DEBUG("Received ACK from=" << sender);
1270
1272
1273 // When fragmentation is used, only update manager when the last fragment is acknowledged
1274 if (!mpdu->GetHeader().IsMoreFragments())
1275 {
1276 GetWifiRemoteStationManager()->ReportRxOk(sender, rxInfo, ackTxVector);
1278 rxInfo.snr,
1279 ackTxVector.GetMode(),
1280 snr,
1281 txVector);
1282 }
1283 // cancel the timer
1284 m_txTimer.Cancel();
1286
1287 // The CW shall be reset to aCWmin after every successful attempt to transmit
1288 // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1290
1291 if (mpdu->GetHeader().IsMoreFragments())
1292 {
1293 // replace the current fragment with the next one
1294 m_dcf->GetWifiMacQueue()->Replace(mpdu, GetNextFragment());
1295 m_moreFragments = true;
1296 }
1297 else
1298 {
1299 // the MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1300 DequeueMpdu(mpdu);
1301 }
1302
1304}
1305
1306void
1308{
1309 NS_LOG_FUNCTION(this << *mpdu);
1310
1311 // inform the MAC that the transmission was successful
1313 {
1314 m_ackedMpduCallback(mpdu);
1315 }
1316}
1317
1318void
1320 const RxSignalInfo& rxSignalInfo,
1321 const WifiTxVector& txVector,
1322 const std::vector<bool>& perMpduStatus)
1323{
1324 NS_ASSERT_MSG(false, "A non-QoS station should not receive an A-MPDU");
1325}
1326
1327} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
bool IsNull() const
Check for null implementation.
Definition: callback.h:556
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
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 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.
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 ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector)
Forward an MPDU down to the PHY layer.
void SetLinkId(uint8_t linkId)
Set the ID of the link this Frame Exchange Manager is associated with.
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 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.
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.
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 ReleaseSequenceNumber(Ptr< WifiMpdu > mpdu) const
Make the sequence number of the given MPDU available again if the MPDU has never been transmitted.
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:369
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:397
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:863
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
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
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< WifiMpdu > item=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
Definition: qos-txop.cc:368
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
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
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
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:300
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:220
virtual void NotifyChannelReleased(uint8_t linkId)
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: txop.cc:585
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:291
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:646
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:578
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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.
uint16_t GetRawDuration() const
Return the raw duration from the Duration/ID field.
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:555
represent a single transmission mode
Definition: wifi-mode.h:50
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:1635
Time GetSlot() const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:740
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:728
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1422
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:950
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:417
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1415
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:269
Time GetDuration() const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition: wifi-psdu.cc:143
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:323
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:113
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:317
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:734
#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:45
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1374
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
address
Definition: first.py:40
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 octects 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:691
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
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition: wifi-mac.h:76
mac
Definition: third.py:85
phy
Definition: third.py:82
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.