A Discrete-Event Network Simulator
API
frame-exchange-manager.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Stefano Avallone <stavallo@unina.it>
19 */
20
21#include "ns3/log.h"
22#include "ns3/abort.h"
25#include "wifi-utils.h"
26#include "snr-tag.h"
27#include "wifi-mac-queue.h"
28#include "wifi-mac-trailer.h"
29
30#undef NS_LOG_APPEND_CONTEXT
31#define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
32
33// Time (in nanoseconds) to be added to the PSDU duration to yield the duration
34// of the timer that is started when the PHY indicates the start of the reception
35// of a frame and we are waiting for a response.
36#define PSDU_DURATION_SAFEGUARD 400
37
38namespace ns3 {
39
40NS_LOG_COMPONENT_DEFINE ("FrameExchangeManager");
41
42NS_OBJECT_ENSURE_REGISTERED (FrameExchangeManager);
43
44TypeId
46{
47 static TypeId tid = TypeId ("ns3::FrameExchangeManager")
48 .SetParent<Object> ()
49 .AddConstructor<FrameExchangeManager> ()
50 .SetGroupName ("Wifi")
51 ;
52 return tid;
53}
54
56 : m_navEnd (Seconds (0)),
57 m_linkId (0),
58 m_allowedWidth (0),
59 m_promisc (false),
60 m_moreFragments (false)
61{
62 NS_LOG_FUNCTION (this);
63}
64
66{
68}
69
70void
72{
73 NS_LOG_FUNCTION (this);
76 {
78 }
80 m_mpdu = 0;
82 m_dcf = 0;
83}
84
85void
87{
88 NS_LOG_FUNCTION (this);
89 Reset ();
91 m_mac = 0;
92 m_txMiddle = 0;
93 m_rxMiddle = 0;
96 m_ackManager = 0;
97 if (m_phy)
98 {
99 m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
101 }
102 m_phy = 0;
104}
105
106void
108{
109 NS_LOG_FUNCTION (this << protectionManager);
110 m_protectionManager = protectionManager;
111}
112
115{
116 return m_protectionManager;
117}
118
119void
121{
122 NS_LOG_FUNCTION (this << ackManager);
123 m_ackManager = ackManager;
124}
125
128{
129 return m_ackManager;
130}
131
132void
134{
135 NS_LOG_FUNCTION (this << +linkId);
136 m_linkId = linkId;
137}
138
139void
141{
142 NS_LOG_FUNCTION (this << mac);
143 m_mac = mac;
144}
145
146void
148{
149 NS_LOG_FUNCTION (this << txMiddle);
150 m_txMiddle = txMiddle;
151}
152
153void
155{
156 NS_LOG_FUNCTION (this << rxMiddle);
157 m_rxMiddle = rxMiddle;
158}
159
160void
162{
163 NS_LOG_FUNCTION (this << channelAccessManager);
164 m_channelAccessManager = channelAccessManager;
165}
166
169{
170 return m_mac->GetWifiRemoteStationManager (m_linkId);
171}
172
173void
175{
176 NS_LOG_FUNCTION (this << phy);
177 m_phy = phy;
178 m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin",
181}
182
183void
185{
186 NS_LOG_FUNCTION (this);
187 if (m_phy)
188 {
189 m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
192 m_phy = nullptr;
193 }
194}
195
196void
198{
199 NS_LOG_FUNCTION (this << address);
200 // For APs, the BSSID is the MAC address. For STAs, the BSSID will be overwritten
201 // when receiving Beacon frames or Probe Response frames
203 m_self = address;
204}
205
208{
209 return m_self;
210}
211
212void
214{
215 NS_LOG_FUNCTION (this << bssid);
216 m_bssid = bssid;
217}
218
221{
222 return m_bssid;
223}
224
225void
227{
228 NS_LOG_FUNCTION (this << &callback);
229 m_droppedMpduCallback = callback;
230}
231
232void
234{
235 NS_LOG_FUNCTION (this << &callback);
236 m_ackedMpduCallback = callback;
237}
238
239void
241{
242 m_promisc = true;
243}
244
245bool
247{
248 return m_promisc;
249}
250
251const WifiTxTimer&
253{
254 return m_txTimer;
255}
256
257void
259{
261 {
263 }
264}
265
266void
268{
269 NS_LOG_FUNCTION (this << "PSDU reception started for " << psduDuration.As (Time::US)
270 << " (txVector: " << txVector << ")");
271
273 "The TX timer and the NAV reset event cannot be both running");
274
275 // No need to reschedule timeouts if PSDU duration is null. In this case,
276 // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered)
277 // and CCA will take over
278 if (m_txTimer.IsRunning () && psduDuration.IsStrictlyPositive ())
279 {
280 // we are waiting for a response and something arrived
281 NS_LOG_DEBUG ("Rescheduling timeout event");
283 // PHY has switched to RX, so we can reset the ack timeout
285 }
286
288 {
290 }
291}
292
293bool
295{
296 NS_LOG_FUNCTION (this << dcf << allowedWidth);
297
298 NS_ASSERT (!m_mpdu);
299 if (m_txTimer.IsRunning ())
300 {
301 m_txTimer.Cancel ();
302 }
303 m_dcf = dcf;
304 m_allowedWidth = allowedWidth;
305
306 Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue ();
307
308 // Even though channel access is requested when the queue is not empty, at
309 // the time channel access is granted the lifetime of the packet might be
310 // expired and the queue might be empty.
311 queue->WipeAllExpiredMpdus ();
312
313 Ptr<WifiMpdu> mpdu = queue->Peek (m_linkId);
314
315 if (!mpdu)
316 {
317 NS_LOG_DEBUG ("Queue empty");
319 m_dcf = 0;
320 return false;
321 }
322
324
325 NS_ASSERT (mpdu->GetHeader ().IsData () || mpdu->GetHeader ().IsMgt ());
326
327 // assign a sequence number if this is not a fragment nor a retransmission
328 if (!mpdu->IsFragment () && !mpdu->GetHeader ().IsRetry ())
329 {
330 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&mpdu->GetHeader ());
331 mpdu->GetHeader ().SetSequenceNumber (sequence);
332 }
333
334 NS_LOG_DEBUG ("MPDU payload size=" << mpdu->GetPacketSize () <<
335 ", to=" << mpdu->GetHeader ().GetAddr1 () <<
336 ", seq=" << mpdu->GetHeader ().GetSequenceControl ());
337
338 // check if the MSDU needs to be fragmented
339 mpdu = GetFirstFragmentIfNeeded (mpdu);
340
343 WifiTxParameters txParams;
344 txParams.m_txVector = GetWifiRemoteStationManager ()->GetDataTxVector (mpdu->GetHeader (), m_allowedWidth);
345 txParams.m_protection = m_protectionManager->TryAddMpdu (mpdu, txParams);
346 txParams.m_acknowledgment = m_ackManager->TryAddMpdu (mpdu, txParams);
347 txParams.AddMpdu (mpdu);
348 UpdateTxDuration (mpdu->GetHeader ().GetAddr1 (), txParams);
349
350 SendMpduWithProtection (mpdu, txParams);
351
352 return true;
353}
354
357{
358 NS_LOG_FUNCTION (this << *mpdu);
359
360 if (mpdu->IsFragment ())
361 {
362 // a fragment cannot be further fragmented
364 }
365 else if (GetWifiRemoteStationManager ()->NeedFragmentation (mpdu))
366 {
367 NS_LOG_DEBUG ("Fragmenting the MSDU");
368 m_fragmentedPacket = mpdu->GetPacket ()->Copy ();
369 // create the first fragment
370 Ptr<Packet> fragment = m_fragmentedPacket->CreateFragment (0, GetWifiRemoteStationManager ()->GetFragmentSize (mpdu, 0));
371 // enqueue the first fragment
372 Ptr<WifiMpdu> item = Create<WifiMpdu> (fragment, mpdu->GetHeader ());
373 item->GetHeader ().SetMoreFragments ();
374 m_mac->GetTxopQueue (mpdu->GetQueueAc ())->Replace (mpdu, item);
375 return item;
376 }
377 return mpdu;
378}
379
380void
382{
383 NS_LOG_FUNCTION (this << *mpdu << &txParams);
384
385 m_mpdu = mpdu;
386 m_txParams = std::move (txParams);
387
388 // If protection is required, the MPDU must be stored in some queue because
389 // it is not put back in a queue if the RTS/CTS exchange fails
391 || m_mpdu->GetHeader ().IsCtl ()
392 || m_mpdu->IsQueued ());
393
394 // Make sure that the acknowledgment time has been computed, so that SendRts()
395 // and SendCtsToSelf() can reuse this value.
397
398 if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min ())
399 {
401 }
402
403 // Set QoS Ack policy if this is a QoS data frame
405
406 switch (m_txParams.m_protection->method)
407 {
410 break;
413 break;
415 SendMpdu ();
416 break;
417 default:
418 NS_ABORT_MSG ("Unknown protection type");
419 }
420}
421
422void
424{
425 NS_LOG_FUNCTION (this);
426
429
431
433 {
435
436 if (!m_mpdu->GetHeader ().IsQosData ()
437 || m_mpdu->GetHeader ().GetQosAckPolicy () == WifiMacHeader::NO_ACK)
438 {
439 // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
441 }
442 }
444 {
445 m_mpdu->GetHeader ().SetDuration (GetFrameDurationId (m_mpdu->GetHeader (),
448
449 // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
450 // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
451 // aRxPHYStartDelay equals the time to transmit the PHY header.
452 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (m_txParams.m_acknowledgment.get ());
453
454 Time timeout = txDuration
455 + m_phy->GetSifs ()
456 + m_phy->GetSlot ()
462 }
463 else
464 {
465 NS_ABORT_MSG ("Unable to handle the selected acknowledgment method ("
466 << m_txParams.m_acknowledgment.get () << ")");
467 }
468
469 // transmit the MPDU
471
473 {
474 // we are done with frames that do not require acknowledgment
475 m_mpdu = 0;
476 }
477}
478
479void
481{
482 NS_LOG_FUNCTION (this << *mpdu << txVector);
483
484 m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
485}
486
487void
489{
490 NS_LOG_DEBUG (this << *mpdu);
491
492 if (mpdu->IsQueued ())
493 {
494 m_mac->GetTxopQueue (mpdu->GetQueueAc ())->DequeueIfQueued ({mpdu});
495 }
496}
497
500{
501 return mpdu->GetSize ();
502}
503
504void
506{
507 NS_LOG_FUNCTION (this << protection);
508 NS_ASSERT (protection);
509
510 if (protection->method == WifiProtection::NONE)
511 {
512 protection->protectionTime = Seconds (0);
513 }
514 else if (protection->method == WifiProtection::RTS_CTS)
515 {
516 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (protection);
517 rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration (GetRtsSize (), rtsCtsProtection->rtsTxVector,
518 m_phy->GetPhyBand ())
519 + m_phy->CalculateTxDuration (GetCtsSize (), rtsCtsProtection->ctsTxVector,
520 m_phy->GetPhyBand ())
521 + 2 * m_phy->GetSifs ();
522 }
523 else if (protection->method == WifiProtection::CTS_TO_SELF)
524 {
525 WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (protection);
526 ctsToSelfProtection->protectionTime = m_phy->CalculateTxDuration (GetCtsSize (),
527 ctsToSelfProtection->ctsTxVector,
528 m_phy->GetPhyBand ())
529 + m_phy->GetSifs ();
530 }
531}
532
533void
535{
536 NS_LOG_FUNCTION (this << acknowledgment);
537 NS_ASSERT (acknowledgment);
538
539 if (acknowledgment->method == WifiAcknowledgment::NONE)
540 {
541 acknowledgment->acknowledgmentTime = Seconds (0);
542 }
543 else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
544 {
545 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (acknowledgment);
546 normalAcknowledgment->acknowledgmentTime = m_phy->GetSifs ()
548 normalAcknowledgment->ackTxVector,
549 m_phy->GetPhyBand ());
550 }
551}
552
553Time
555 const WifiTxParameters& txParams) const
556{
557 return m_phy->CalculateTxDuration (ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand ());
558}
559
560void
562{
563 txParams.m_txDuration = GetTxDuration (txParams.GetSize (receiver), receiver, txParams);
564}
565
566Time
568 const WifiTxParameters& txParams,
569 Ptr<Packet> fragmentedPacket) const
570{
571 NS_LOG_FUNCTION (this << header << size << &txParams << fragmentedPacket);
572
573 NS_ASSERT (txParams.m_acknowledgment && txParams.m_acknowledgment->acknowledgmentTime != Time::Min ());
574 Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
575
576 // if the current frame is a fragment followed by another fragment, we have to
577 // update the Duration/ID to cover the next fragment and the corresponding Ack
578 if (header.IsMoreFragments ())
579 {
580 uint32_t payloadSize = size - header.GetSize () - WIFI_MAC_FCS_LENGTH;
581 uint32_t nextFragmentOffset = (header.GetFragmentNumber () + 1) * payloadSize;
582 uint32_t nextFragmentSize = std::min (fragmentedPacket->GetSize () - nextFragmentOffset,
583 payloadSize);
585 txParams.m_txVector);
586
587 durationId += 2 * m_phy->GetSifs ()
588 + m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ())
589 + m_phy->CalculateTxDuration (nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand ());
590 }
591 return durationId;
592}
593
594Time
595FrameExchangeManager::GetRtsDurationId (const WifiTxVector& rtsTxVector, Time txDuration, Time response) const
596{
597 NS_LOG_FUNCTION (this << rtsTxVector << txDuration << response);
598
599 WifiTxVector ctsTxVector;
600 ctsTxVector = GetWifiRemoteStationManager ()->GetCtsTxVector (m_self, rtsTxVector.GetMode ());
601
602 return m_phy->GetSifs ()
603 + m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ()) /* CTS */
604 + m_phy->GetSifs () + txDuration + response;
605}
606
607void
609{
610 NS_LOG_FUNCTION (this << &txParams);
611
612 NS_ASSERT (txParams.GetPsduInfoMap ().size () == 1);
613 Mac48Address receiver = txParams.GetPsduInfoMap ().begin ()->first;
614
615 WifiMacHeader rts;
617 rts.SetDsNotFrom ();
618 rts.SetDsNotTo ();
619 rts.SetNoRetry ();
620 rts.SetNoMoreFragments ();
621 rts.SetAddr1 (receiver);
622 rts.SetAddr2 (m_self);
623
624 NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
625 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (txParams.m_protection.get ());
626
627 NS_ASSERT (txParams.m_txDuration != Time::Min ());
628 rts.SetDuration (GetRtsDurationId (rtsCtsProtection->rtsTxVector, txParams.m_txDuration,
629 txParams.m_acknowledgment->acknowledgmentTime));
630 Ptr<WifiMpdu> mpdu = Create<WifiMpdu> (Create<Packet> (), rts);
631
632 // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
633 // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
634 // aRxPHYStartDelay equals the time to transmit the PHY header.
636 + m_phy->GetSifs ()
637 + m_phy->GetSlot ()
641 mpdu, rtsCtsProtection->rtsTxVector);
643
644 ForwardMpduDown (mpdu, rtsCtsProtection->rtsTxVector);
645}
646
647void
649 double rtsSnr)
650{
651 NS_LOG_FUNCTION (this << rtsHdr << ctsTxVector << rtsSnr);
652
653 WifiMacHeader cts;
655 cts.SetDsNotFrom ();
656 cts.SetDsNotTo ();
657 cts.SetNoMoreFragments ();
658 cts.SetNoRetry ();
659 cts.SetAddr1 (rtsHdr.GetAddr2 ());
660 Time duration = rtsHdr.GetDuration () - m_phy->GetSifs ()
661 - m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
662 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
663 if (duration.IsStrictlyNegative ())
664 {
665 duration = Seconds (0);
666 }
667 cts.SetDuration (duration);
668
669 Ptr<Packet> packet = Create<Packet> ();
670
671 SnrTag tag;
672 tag.Set (rtsSnr);
673 packet->AddPacketTag (tag);
674
675 // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
676 ForwardMpduDown (Create<WifiMpdu> (packet, cts), ctsTxVector);
677}
678
679void
680FrameExchangeManager::SendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiMode rtsTxMode, double rtsSnr)
681{
682 NS_LOG_FUNCTION (this << rtsHdr << rtsTxMode << rtsSnr);
683
684 WifiTxVector ctsTxVector = GetWifiRemoteStationManager ()->GetCtsTxVector (rtsHdr.GetAddr2 (), rtsTxMode);
685 DoSendCtsAfterRts (rtsHdr, ctsTxVector, rtsSnr);
686}
687
688Time
690 Time txDuration, Time response) const
691{
692 NS_LOG_FUNCTION (this << ctsTxVector << txDuration << response);
693
694 return m_phy->GetSifs () + txDuration + response;
695}
696
697void
699{
700 NS_LOG_FUNCTION (this << &txParams);
701
702 WifiMacHeader cts;
704 cts.SetDsNotFrom ();
705 cts.SetDsNotTo ();
706 cts.SetNoMoreFragments ();
707 cts.SetNoRetry ();
708 cts.SetAddr1 (m_self);
709
710 NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
711 WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (txParams.m_protection.get ());
712
713 NS_ASSERT (txParams.m_txDuration != Time::Min ());
714 cts.SetDuration (GetCtsToSelfDurationId (ctsToSelfProtection->ctsTxVector, txParams.m_txDuration,
715 txParams.m_acknowledgment->acknowledgmentTime));
716
717 ForwardMpduDown (Create<WifiMpdu> (Create<Packet> (), cts), ctsToSelfProtection->ctsTxVector);
718
719 Time ctsDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsToSelfProtection->ctsTxVector,
720 m_phy->GetPhyBand ());
722}
723
724void
726 double dataSnr)
727{
728 NS_LOG_FUNCTION (this << hdr << dataTxVector << dataSnr);
729
730 WifiTxVector ackTxVector = GetWifiRemoteStationManager ()->GetAckTxVector (hdr.GetAddr2 (), dataTxVector);
731 WifiMacHeader ack;
733 ack.SetDsNotFrom ();
734 ack.SetDsNotTo ();
735 ack.SetNoRetry ();
736 ack.SetNoMoreFragments ();
737 ack.SetAddr1 (hdr.GetAddr2 ());
738 // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
739 // minus the time to transmit the Ack frame and its SIFS interval
740 Time duration = hdr.GetDuration () - m_phy->GetSifs ()
741 - m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ());
742 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
743 if (duration.IsStrictlyNegative ())
744 {
745 duration = Seconds (0);
746 }
747 ack.SetDuration (duration);
748
749 Ptr<Packet> packet = Create<Packet> ();
750
751 SnrTag tag;
752 tag.Set (dataSnr);
753 packet->AddPacketTag (tag);
754
755 ForwardMpduDown (Create<WifiMpdu> (packet, ack), ackTxVector);
756}
757
760{
761 NS_LOG_FUNCTION (this);
762 NS_ASSERT (m_mpdu->GetHeader ().IsMoreFragments ());
763
764 WifiMacHeader& hdr = m_mpdu->GetHeader ();
765 hdr.SetFragmentNumber (hdr.GetFragmentNumber () + 1);
766
767 uint32_t startOffset = hdr.GetFragmentNumber () * m_mpdu->GetPacketSize ();
768 uint32_t size = m_fragmentedPacket->GetSize () - startOffset;
769
770 if (size > m_mpdu->GetPacketSize ())
771 {
772 // this is not the last fragment
773 size = m_mpdu->GetPacketSize ();
774 hdr.SetMoreFragments ();
775 }
776 else
777 {
778 hdr.SetNoMoreFragments ();
779 }
780
781 return Create<WifiMpdu> (m_fragmentedPacket->CreateFragment (startOffset, size), hdr);
782}
783
784void
786{
787 NS_LOG_FUNCTION (this);
788
789 // Upon a transmission success, a non-QoS station transmits the next fragment,
790 // if any, or releases the channel, otherwise
791 if (m_moreFragments)
792 {
793 NS_LOG_DEBUG ("Schedule transmission of next fragment in a SIFS");
795 this, m_dcf, m_allowedWidth);
796 m_moreFragments = false;
797 }
798 else
799 {
801 m_dcf = 0;
802 }
803}
804
805void
807{
808 NS_LOG_FUNCTION (this);
809 // A non-QoS station always releases the channel upon a transmission failure
811 m_dcf = 0;
812}
813
814void
816{
817 NS_LOG_FUNCTION (this << *mpdu << txVector);
818
820
821 if (!GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
822 {
823 NS_LOG_DEBUG ("Missed Ack, discard MPDU");
825 // Dequeue the MPDU if it is stored in a queue
826 DequeueMpdu (mpdu);
829 }
830 else
831 {
832 NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
833 mpdu->GetHeader ().SetRetry ();
836 }
837
838 m_mpdu = 0;
840}
841
842void
844{
845 NS_LOG_FUNCTION (this << *mpdu);
846}
847
848void
850{
851 NS_LOG_FUNCTION (this << *rts << txVector);
852
853 DoCtsTimeout (Create<WifiPsdu> (m_mpdu, true));
854 m_mpdu = nullptr;
855}
856
857void
859{
860 NS_LOG_FUNCTION (this << *psdu);
861
863
864 if (!GetWifiRemoteStationManager ()->NeedRetransmission (*psdu->begin ()))
865 {
866 NS_LOG_DEBUG ("Missed CTS, discard MPDU(s)");
868 for (const auto& mpdu : *PeekPointer (psdu))
869 {
870 // Dequeue the MPDU if it is stored in a queue
871 DequeueMpdu (mpdu);
873 }
875 }
876 else
877 {
878 NS_LOG_DEBUG ("Missed CTS, retransmit MPDU(s)");
880 }
881 // Make the sequence numbers of the MPDUs available again if the MPDUs have never
882 // been transmitted, both in case the MPDUs have been discarded and in case the
883 // MPDUs have to be transmitted (because a new sequence number is assigned to
884 // MPDUs that have never been transmitted and are selected for transmission)
885 for (const auto& mpdu : *PeekPointer (psdu))
886 {
888 }
890}
891
892void
894{
895 NS_LOG_FUNCTION (this << *mpdu);
896
897 // the MPDU should be still in the DCF queue, unless it expired.
898 // If the MPDU has never been transmitted, it will be assigned a sequence
899 // number again the next time we try to transmit it. Therefore, we need to
900 // make its sequence number available again
901 if (!mpdu->GetHeader ().IsRetry ())
902 {
903 m_txMiddle->SetSequenceNumberFor (&mpdu->GetHeader ());
904 }
905}
906
907void
909{
910 NS_LOG_FUNCTION (this);
911
912 // For internal collisions occurring with the EDCA access method, the appropriate
913 // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
914 // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
915 // (Sec. 10.22.2.11.1 of 802.11-2016).
916 // We do not prepare the PSDU that the AC losing the internal collision would have
917 // sent. As an approximation, we consider the frame peeked from the queues of the AC.
918 Ptr<QosTxop> qosTxop = (txop->IsQosTxop () ? StaticCast<QosTxop> (txop) : nullptr);
919
920 auto mpdu = (qosTxop ? qosTxop->PeekNextMpdu (m_linkId)
921 : txop->GetWifiMacQueue ()->Peek (m_linkId));
922
923 if (mpdu)
924 {
925 if (mpdu->GetHeader ().HasData ()
926 && !mpdu->GetHeader ().GetAddr1 ().IsGroup ())
927 {
929 }
930
931 if (!mpdu->GetHeader ().GetAddr1 ().IsGroup ()
932 && !GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
933 {
934 NS_LOG_DEBUG ("reset DCF");
936 DequeueMpdu (mpdu);
938 txop->ResetCw (m_linkId);
939 }
940 else
941 {
942 NS_LOG_DEBUG ("Update CW");
943 txop->UpdateFailedCw (m_linkId);
944 }
945 }
946
947 txop->Txop::NotifyChannelReleased (m_linkId);
948}
949
950void
952{
953 NS_LOG_DEBUG ("Switching channel. Cancelling MAC pending events");
955 if (m_txTimer.IsRunning ())
956 {
957 // we were transmitting something before channel switching. Since we will
958 // not be able to receive the response, have the timer expire now, so that
959 // we perform the actions required in case of missing response
961 }
963}
964
965void
967{
968 NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
969 Reset ();
970}
971
972void
974{
975 NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
976 Reset ();
977}
978
979void
981 WifiTxVector txVector, std::vector<bool> perMpduStatus)
982{
983 NS_LOG_FUNCTION (this << psdu << rxSignalInfo << txVector << perMpduStatus.size ()
984 << std::all_of (perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
985
986 if (!perMpduStatus.empty ())
987 {
988 // for A-MPDUs, we get here only once
989 PreProcessFrame (psdu, txVector);
990 }
991
992 // ignore unicast frames that are not addressed to us
993 Mac48Address addr1 = psdu->GetAddr1 ();
994 if (!addr1.IsGroup () && addr1 != m_self)
995 {
996 if (m_promisc && psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsData ())
997 {
998 m_rxMiddle->Receive (*psdu->begin (), m_linkId);
999 }
1000 return;
1001 }
1002
1003 if (psdu->GetNMpdus () == 1)
1004 {
1005 // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
1006 // then it must contain a single value which must be true (i.e., the MPDU
1007 // has been correctly received)
1008 NS_ASSERT (perMpduStatus.empty () || (perMpduStatus.size () == 1 && perMpduStatus[0]));
1009 // Ack and CTS do not carry Addr2
1010 if (!psdu->GetHeader (0).IsAck () && !psdu->GetHeader (0).IsCts ())
1011 {
1013 rxSignalInfo, txVector);
1014 }
1015 ReceiveMpdu (*(psdu->begin ()), rxSignalInfo, txVector, perMpduStatus.empty ());
1016 }
1017 else
1018 {
1019 EndReceiveAmpdu (psdu, rxSignalInfo, txVector, perMpduStatus);
1020 }
1021}
1022
1023void
1025{
1026 NS_LOG_FUNCTION (this << psdu << txVector);
1027
1028 UpdateNav (psdu, txVector);
1029}
1030
1031void
1033{
1034 NS_LOG_FUNCTION (this << psdu << txVector);
1035
1036 if (psdu->GetHeader (0).GetRawDuration () > 32767)
1037 {
1038 // When the contents of a received Duration/ID field, treated as an unsigned
1039 // integer, are greater than 32 768, the contents are interpreted as appropriate
1040 // for the frame type and subtype or ignored if the receiving MAC entity does
1041 // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
1042 // sec. 10.27.3)
1043 return;
1044 }
1045
1046 Time duration = psdu->GetDuration ();
1047 NS_LOG_DEBUG ("Duration/ID=" << duration);
1048
1049 if (psdu->GetAddr1 () == m_self)
1050 {
1051 // When the received frame’s RA is equal to the STA’s own MAC address, the STA
1052 // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
1053 return;
1054 }
1055
1056 // For all other received frames the STA shall update its NAV when the received
1057 // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
1058 Time navEnd = Simulator::Now () + duration;
1059 if (navEnd > m_navEnd)
1060 {
1061 m_navEnd = navEnd;
1062 NS_LOG_DEBUG ("Updated NAV=" << m_navEnd);
1063
1064 // A STA that used information from an RTS frame as the most recent basis to update
1065 // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
1066 // primitive is received from the PHY during a NAVTimeout period starting when the
1067 // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
1068 // the RTS frame. NAVTimeout period is equal to:
1069 // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
1070 // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
1071 // rate at which the RTS frame used for the most recent NAV update was received
1072 // (IEEE 802.11-2016 sec. 10.3.2.4)
1073 if (psdu->GetHeader (0).IsRts ())
1074 {
1075 Time navResetDelay = 2 * m_phy->GetSifs ()
1077 m_phy->GetPhyBand ())
1079 + 2 * m_phy->GetSlot ();
1081 }
1082 }
1083 NS_LOG_DEBUG ("Current NAV=" << m_navEnd);
1084
1086}
1087
1088void
1090{
1091 NS_LOG_FUNCTION (this);
1094}
1095
1096void
1098 const WifiTxVector& txVector, bool inAmpdu)
1099{
1100 NS_LOG_FUNCTION (this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1101 // The received MPDU is either broadcast or addressed to this station
1102 NS_ASSERT (mpdu->GetHeader ().GetAddr1 ().IsGroup ()
1103 || mpdu->GetHeader ().GetAddr1 () == m_self);
1104
1105 double rxSnr = rxSignalInfo.snr;
1106 const WifiMacHeader& hdr = mpdu->GetHeader ();
1107
1108 if (hdr.IsCtl ())
1109 {
1110 if (hdr.IsRts ())
1111 {
1112 NS_ABORT_MSG_IF (inAmpdu, "Received RTS as part of an A-MPDU");
1113
1114 // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1115 // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1116 // - Otherwise, the STA shall not respond with a CTS frame
1117 // (IEEE 802.11-2016 sec. 10.3.2.7)
1118 if (m_navEnd <= Simulator::Now ())
1119 {
1120 NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
1122 this, hdr, txVector.GetMode (), rxSnr);
1123 }
1124 else
1125 {
1126 NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
1127 }
1128 }
1129 else if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS
1130 && m_mpdu)
1131 {
1132 NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU");
1133 NS_ASSERT (hdr.GetAddr1 () == m_self);
1134
1135 Mac48Address sender = m_mpdu->GetHeader ().GetAddr1 ();
1136 NS_LOG_DEBUG ("Received CTS from=" << sender);
1137
1138 SnrTag tag;
1139 mpdu->GetPacket ()->PeekPacketTag (tag);
1140 GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector);
1142 rxSnr, txVector.GetMode (), tag.Get ());
1143
1144 m_txTimer.Cancel ();
1147 }
1148 else if (hdr.IsAck () && m_mpdu && m_txTimer.IsRunning ()
1150 {
1151 NS_ASSERT (hdr.GetAddr1 () == m_self);
1152 SnrTag tag;
1153 mpdu->GetPacket ()->PeekPacketTag (tag);
1154 ReceivedNormalAck (m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ());
1155 m_mpdu = 0;
1156 }
1157 }
1158 else if (hdr.IsMgt ())
1159 {
1160 NS_ABORT_MSG_IF (inAmpdu, "Received management frame as part of an A-MPDU");
1161
1162 if (hdr.IsBeacon () || hdr.IsProbeResp ())
1163 {
1164 // Apply SNR tag for beacon quality measurements
1165 SnrTag tag;
1166 tag.Set (rxSnr);
1167 Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
1168 packet->AddPacketTag (tag);
1169 mpdu = Create<WifiMpdu> (packet, hdr);
1170 }
1171
1172 if (hdr.GetAddr1 () == m_self)
1173 {
1174 NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1176 this, hdr, txVector, rxSnr);
1177 }
1178
1179 m_rxMiddle->Receive (mpdu, m_linkId);
1180 }
1181 else if (hdr.IsData () && !hdr.IsQosData ())
1182 {
1183 if (hdr.GetAddr1 () == m_self)
1184 {
1185 NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1187 this, hdr, txVector, rxSnr);
1188 }
1189
1190 m_rxMiddle->Receive (mpdu, m_linkId);
1191 }
1192}
1193
1194void
1196 const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo,
1197 double snr)
1198{
1199 Mac48Address sender = mpdu->GetHeader ().GetAddr1 ();
1200 NS_LOG_DEBUG ("Received ACK from=" << sender);
1201
1203
1204 // When fragmentation is used, only update manager when the last fragment is acknowledged
1205 if (!mpdu->GetHeader ().IsMoreFragments ())
1206 {
1207 GetWifiRemoteStationManager ()->ReportRxOk (sender, rxInfo, ackTxVector);
1208 GetWifiRemoteStationManager ()->ReportDataOk (mpdu, rxInfo.snr, ackTxVector.GetMode (),
1209 snr, txVector);
1210 }
1211 // cancel the timer
1212 m_txTimer.Cancel ();
1214
1215 // The CW shall be reset to aCWmin after every successful attempt to transmit
1216 // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1218
1219 if (mpdu->GetHeader ().IsMoreFragments ())
1220 {
1221 // replace the current fragment with the next one
1222 m_dcf->GetWifiMacQueue ()->Replace (mpdu, GetNextFragment ());
1223 m_moreFragments = true;
1224 }
1225 else
1226 {
1227 // the MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1228 DequeueMpdu (mpdu);
1229 }
1230
1232}
1233
1234void
1236{
1237 NS_LOG_FUNCTION (this << *mpdu);
1238
1239 // inform the MAC that the transmission was successful
1241 {
1242 m_ackedMpduCallback (mpdu);
1243 }
1244}
1245
1246void
1248 const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus)
1249{
1250 NS_ASSERT_MSG (false, "A non-QoS station should not receive an A-MPDU");
1251}
1252
1253} //namespace ns3
#define min(a, b)
Definition: 80211b.c:42
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:532
void NotifyCtsTimeoutResetNow(void)
Notify that CTS 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 NotifyAckTimeoutResetNow(void)
Notify that ack timer has reset.
void NotifyNavResetNow(Time duration)
void NotifyNavStartNow(Time duration)
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
Mac48Address GetBssid(void) const
Get the Basic Service Set Identification.
void SetPromisc(void)
Enable promiscuous mode.
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(void)
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.
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 TransmissionSucceeded(void)
Take necessary actions upon a transmission success.
const WifiTxTimer & GetWifiTxTimer(void) const
Get a const reference to the WifiTxTimer object.
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.
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.
static TypeId GetTypeId(void)
Get the type ID.
Mac48Address m_self
the MAC address of this device
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.
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)
Ptr< WifiProtectionManager > GetProtectionManager(void) const
Get the Protection Manager used by this node.
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.
virtual void DequeueMpdu(Ptr< const WifiMpdu > mpdu)
Dequeue the given MPDU from the queue in which it is stored.
Ptr< WifiMpdu > GetNextFragment(void)
Get the next fragment of the current MSDU.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(void) const
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
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.
virtual void TransmissionFailed(void)
Take necessary actions upon a transmission failure.
Ptr< WifiAckManager > GetAckManager(void) const
Get the Acknowledgment Manager used by this node.
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.
Mac48Address GetAddress(void) const
Get the MAC address.
void SendMpdu(void)
Send the current MPDU, which can be acknowledged by a Normal Ack.
void NotifySleepNow(void)
This method is typically invoked by the PhyListener to notify the MAC layer that the device has been ...
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.
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
Time m_navEnd
NAV expiration time.
virtual void NavResetTimeout(void)
Reset the NAV upon expiration of the NAV reset timer.
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.
bool IsPromisc(void) const
Check if the device is operating in promiscuous mode.
virtual void Reset(void)
Reset this frame exchange manager.
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
virtual void ResetPhy(void)
Remove WifiPhy associated with this FrameExchangeManager.
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:44
bool IsGroup(void) const
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:390
A base class which provides memory management and object aggregation.
Definition: object.h:88
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
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:354
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:555
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:586
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
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:83
double Get(void) const
Return the SNR value.
Definition: snr-tag.cc:89
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:333
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:274
@ US
microsecond
Definition: nstime.h:117
bool IsStrictlyNegative(void) const
Exactly equivalent to t < 0.
Definition: nstime.h:325
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:418
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:284
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:204
virtual void NotifyChannelReleased(uint8_t linkId)
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: txop.cc:566
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:275
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:627
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:559
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
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.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
bool IsCtl(void) const
Return true if the Type is Control.
bool IsAck(void) const
Return true if the header is an Ack header.
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
bool IsRts(void) const
Return true if the header is a RTS header.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
bool IsCts(void) const
Return true if the header is a CTS header.
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint16_t GetRawDuration(void) const
Return the raw duration from the Duration/ID field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
bool IsProbeResp(void) const
Return true if the header is a Probe Response header.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
const char * GetTypeString(void) const
Return a string corresponds to the header type.
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
bool IsMgt(void) const
Return true if the Type is Management.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
bool IsData(void) const
Return true if the Type is DATA.
void SetMoreFragments(void)
Set the More Fragment bit in the Frame Control field.
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
void SetFragmentNumber(uint8_t frag)
Set the fragment number of the header.
uint8_t GetFragmentNumber(void) const
Return the fragment number of the header.
bool IsBeacon(void) const
Return true if the header is a Beacon header.
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition: wifi-mac.cc:524
represent a single transmission mode
Definition: wifi-mode.h:48
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:1568
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:938
Time GetSlot(void) const
Return the slot duration 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:1389
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:716
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:411
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1383
Time GetDuration(void) const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition: wifi-psdu.cc:141
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:313
std::vector< Ptr< WifiMpdu > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:319
Mac48Address GetAddr1(void) const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:111
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,...
void Clear(void)
Reset the TX parameters.
const PsduInfoMap & GetPsduInfoMap(void) 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.
This class is used to handle the timer that a station starts when transmitting a frame that solicits ...
Definition: wifi-tx-timer.h:48
Reason GetReason(void) const
Get the reason why the timer was started.
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.
bool IsRunning(void) const
Return true if the timer is running.
void Cancel(void)
Cancel the timer.
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:67
#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:88
Callback< R, Args... > MakeNullCallback(void)
Definition: callback.h:697
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#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:206
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:274
#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:1269
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
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:489
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:661
uint32_t GetAckSize(void)
Return the total Ack size (including FCS trailer).
Definition: wifi-utils.cc:55
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:100
uint32_t GetCtsSize(void)
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:108
@ WIFI_MAC_CTL_RTS
@ WIFI_MAC_CTL_CTS
@ WIFI_MAC_CTL_ACK
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition: wifi-mac.h:75
mac
Definition: third.py:87
phy
Definition: third.py:84
ns3::Time timeout
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double snr
SNR in linear scale.
Definition: phy-entity.h:70
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.