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"
24#include "wifi-utils.h"
25#include "snr-tag.h"
26#include "wifi-mac-queue.h"
27#include "wifi-mac-trailer.h"
28
29#undef NS_LOG_APPEND_CONTEXT
30#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
31
32// Time (in nanoseconds) to be added to the PSDU duration to yield the duration
33// of the timer that is started when the PHY indicates the start of the reception
34// of a frame and we are waiting for a response.
35#define PSDU_DURATION_SAFEGUARD 400
36
37namespace ns3 {
38
39NS_LOG_COMPONENT_DEFINE ("FrameExchangeManager");
40
41NS_OBJECT_ENSURE_REGISTERED (FrameExchangeManager);
42
43TypeId
45{
46 static TypeId tid = TypeId ("ns3::FrameExchangeManager")
47 .SetParent<Object> ()
48 .AddConstructor<FrameExchangeManager> ()
49 .SetGroupName ("Wifi")
50 ;
51 return tid;
52}
53
55 : m_navEnd (Seconds (0)),
56 m_promisc (false),
57 m_moreFragments (false)
58{
59 NS_LOG_FUNCTION (this);
60}
61
63{
65}
66
67void
69{
70 NS_LOG_FUNCTION (this);
73 {
75 }
77 m_mpdu = 0;
79 m_dcf = 0;
80}
81
82void
84{
85 NS_LOG_FUNCTION (this);
86 Reset ();
88 m_mac = 0;
89 m_txMiddle = 0;
90 m_rxMiddle = 0;
93 m_ackManager = 0;
94 if (m_phy != 0)
95 {
96 m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
98 }
99 m_phy = 0;
101}
102
103void
105{
106 NS_LOG_FUNCTION (this << protectionManager);
107 m_protectionManager = protectionManager;
108}
109
112{
113 return m_protectionManager;
114}
115
116void
118{
119 NS_LOG_FUNCTION (this << ackManager);
120 m_ackManager = ackManager;
121}
122
125{
126 return m_ackManager;
127}
128
129void
131{
132 NS_LOG_FUNCTION (this << mac);
133 m_mac = mac;
134}
135
136void
138{
139 NS_LOG_FUNCTION (this << txMiddle);
140 m_txMiddle = txMiddle;
141}
142
143void
145{
146 NS_LOG_FUNCTION (this << rxMiddle);
147 m_rxMiddle = rxMiddle;
148}
149
150void
152{
153 NS_LOG_FUNCTION (this << channelAccessManager);
154 m_channelAccessManager = channelAccessManager;
155}
156
157void
159{
160 NS_LOG_FUNCTION (this << phy);
161 m_phy = phy;
162 m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin",
165}
166
167void
169{
170 m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
173 m_phy = 0;
174}
175
176void
178{
179 NS_LOG_FUNCTION (this << address);
180 m_self = address;
181}
182
183void
185{
186 NS_LOG_FUNCTION (this << bssid);
187 m_bssid = bssid;
188}
189
190void
192{
193 NS_LOG_FUNCTION (this << &callback);
194 m_droppedMpduCallback = callback;
195}
196
197void
199{
200 NS_LOG_FUNCTION (this << &callback);
201 m_ackedMpduCallback = callback;
202}
203
204void
206{
207 m_promisc = true;
208}
209
210bool
212{
213 return m_promisc;
214}
215
216const WifiTxTimer&
218{
219 return m_txTimer;
220}
221
222void
224{
226 {
228 }
229}
230
231void
233{
234 NS_LOG_FUNCTION (this << "PSDU reception started for " << psduDuration.As (Time::US)
235 << " (txVector: " << txVector << ")");
236
238 "The TX timer and the NAV reset event cannot be both running");
239
240 // No need to reschedule timeouts if PSDU duration is null. In this case,
241 // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered)
242 // and CCA will take over
243 if (m_txTimer.IsRunning () && psduDuration.IsStrictlyPositive ())
244 {
245 // we are waiting for a response and something arrived
246 NS_LOG_DEBUG ("Rescheduling timeout event");
248 // PHY has switched to RX, so we can reset the ack timeout
249 m_channelAccessManager->NotifyAckTimeoutResetNow ();
250 }
251
253 {
255 }
256}
257
258bool
260{
261 NS_LOG_FUNCTION (this << dcf);
262
263 NS_ASSERT (m_mpdu == 0);
264 if (m_txTimer.IsRunning ())
265 {
266 m_txTimer.Cancel ();
267 }
268 m_dcf = dcf;
269
270 Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue ();
271
272 // Even though channel access is requested when the queue is not empty, at
273 // the time channel access is granted the lifetime of the packet might be
274 // expired and the queue might be empty.
275 if (queue->IsEmpty ())
276 {
277 NS_LOG_DEBUG ("Queue empty");
279 m_dcf = 0;
280 return false;
281 }
282
284 Ptr<WifiMacQueueItem> mpdu = queue->Peek ()->GetItem ();
285 NS_ASSERT (mpdu != 0);
286 NS_ASSERT (mpdu->GetHeader ().IsData () || mpdu->GetHeader ().IsMgt ());
287
288 // assign a sequence number if this is not a fragment nor a retransmission
289 if (!mpdu->IsFragment () && !mpdu->GetHeader ().IsRetry ())
290 {
291 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&mpdu->GetHeader ());
292 mpdu->GetHeader ().SetSequenceNumber (sequence);
293 }
294
295 NS_LOG_DEBUG ("MPDU payload size=" << mpdu->GetPacketSize () <<
296 ", to=" << mpdu->GetHeader ().GetAddr1 () <<
297 ", seq=" << mpdu->GetHeader ().GetSequenceControl ());
298
299 // check if the MSDU needs to be fragmented
300 mpdu = GetFirstFragmentIfNeeded (mpdu);
301
303 NS_ASSERT (m_ackManager != 0);
304 WifiTxParameters txParams;
305 txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (mpdu->GetHeader ());
306 txParams.m_protection = m_protectionManager->TryAddMpdu (mpdu, txParams);
307 txParams.m_acknowledgment = m_ackManager->TryAddMpdu (mpdu, txParams);
308 txParams.AddMpdu (mpdu);
309 UpdateTxDuration (mpdu->GetHeader ().GetAddr1 (), txParams);
310
311 SendMpduWithProtection (mpdu, txParams);
312
313 return true;
314}
315
318{
319 NS_LOG_FUNCTION (this << *mpdu);
320
321 if (mpdu->IsFragment ())
322 {
323 // a fragment cannot be further fragmented
325 }
326 else if (m_mac->GetWifiRemoteStationManager ()->NeedFragmentation (mpdu))
327 {
328 NS_LOG_DEBUG ("Fragmenting the MSDU");
329 m_fragmentedPacket = mpdu->GetPacket ()->Copy ();
330 // create the first fragment
331 Ptr<Packet> fragment = m_fragmentedPacket->CreateFragment (0, m_mac->GetWifiRemoteStationManager ()->GetFragmentSize (mpdu, 0));
332 // enqueue the first fragment
333 Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (fragment, mpdu->GetHeader (), mpdu->GetTimeStamp ());
334 item->GetHeader ().SetMoreFragments ();
335 m_mac->GetTxopQueue (mpdu->GetQueueAc ())->Replace (mpdu, item);
336 return item;
337 }
338 return mpdu;
339}
340
341void
343{
344 NS_LOG_FUNCTION (this << *mpdu << &txParams);
345
346 m_mpdu = mpdu;
347 m_txParams = std::move (txParams);
348
349 // If protection is required, the MPDU must be stored in some queue because
350 // it is not put back in a queue if the RTS/CTS exchange fails
352 || m_mpdu->GetHeader ().IsCtl ()
353 || m_mpdu->IsQueued ());
354
355 // Make sure that the acknowledgment time has been computed, so that SendRts()
356 // and SendCtsToSelf() can reuse this value.
358
359 if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min ())
360 {
362 }
363
364 // Set QoS Ack policy if this is a QoS data frame
366
367 switch (m_txParams.m_protection->method)
368 {
371 break;
374 break;
376 SendMpdu ();
377 break;
378 default:
379 NS_ABORT_MSG ("Unknown protection type");
380 }
381}
382
383void
385{
386 NS_LOG_FUNCTION (this);
387
390
392
394 {
396
397 if (!m_mpdu->GetHeader ().IsQosData ()
398 || m_mpdu->GetHeader ().GetQosAckPolicy () == WifiMacHeader::NO_ACK)
399 {
400 // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
402 }
403 }
405 {
406 m_mpdu->GetHeader ().SetDuration (GetFrameDurationId (m_mpdu->GetHeader (),
409
410 // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
411 // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
412 // aRxPHYStartDelay equals the time to transmit the PHY header.
413 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (m_txParams.m_acknowledgment.get ());
414
415 Time timeout = txDuration
416 + m_phy->GetSifs ()
417 + m_phy->GetSlot ()
422 m_channelAccessManager->NotifyAckTimeoutStartNow (timeout);
423 }
424 else
425 {
426 NS_ABORT_MSG ("Unable to handle the selected acknowledgment method ("
427 << m_txParams.m_acknowledgment.get () << ")");
428 }
429
430 // transmit the MPDU
432
434 {
435 // we are done with frames that do not require acknowledgment
436 m_mpdu = 0;
437 }
438}
439
440void
442{
443 NS_LOG_FUNCTION (this << *mpdu << txVector);
444
445 m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
446}
447
448void
450{
451 NS_LOG_DEBUG (this << *mpdu);
452
453 if (mpdu->IsQueued ())
454 {
455 m_mac->GetTxopQueue (mpdu->GetQueueAc ())->DequeueIfQueued (mpdu);
456 }
457}
458
461{
462 return mpdu->GetSize ();
463}
464
465void
467{
468 NS_LOG_FUNCTION (this << protection);
469 NS_ASSERT (protection != nullptr);
470
471 if (protection->method == WifiProtection::NONE)
472 {
473 protection->protectionTime = Seconds (0);
474 }
475 else if (protection->method == WifiProtection::RTS_CTS)
476 {
477 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (protection);
478 rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration (GetRtsSize (), rtsCtsProtection->rtsTxVector,
479 m_phy->GetPhyBand ())
480 + m_phy->CalculateTxDuration (GetCtsSize (), rtsCtsProtection->ctsTxVector,
481 m_phy->GetPhyBand ())
482 + 2 * m_phy->GetSifs ();
483 }
484 else if (protection->method == WifiProtection::CTS_TO_SELF)
485 {
486 WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (protection);
487 ctsToSelfProtection->protectionTime = m_phy->CalculateTxDuration (GetCtsSize (),
488 ctsToSelfProtection->ctsTxVector,
489 m_phy->GetPhyBand ())
490 + m_phy->GetSifs ();
491 }
492}
493
494void
496{
497 NS_LOG_FUNCTION (this << acknowledgment);
498 NS_ASSERT (acknowledgment != nullptr);
499
500 if (acknowledgment->method == WifiAcknowledgment::NONE)
501 {
502 acknowledgment->acknowledgmentTime = Seconds (0);
503 }
504 else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
505 {
506 WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (acknowledgment);
507 normalAcknowledgment->acknowledgmentTime = m_phy->GetSifs ()
509 normalAcknowledgment->ackTxVector,
510 m_phy->GetPhyBand ());
511 }
512}
513
514Time
516 const WifiTxParameters& txParams) const
517{
518 return m_phy->CalculateTxDuration (ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand ());
519}
520
521void
523{
524 txParams.m_txDuration = GetTxDuration (txParams.GetSize (receiver), receiver, txParams);
525}
526
527Time
529 const WifiTxParameters& txParams,
530 Ptr<Packet> fragmentedPacket) const
531{
532 NS_LOG_FUNCTION (this << header << size << &txParams << fragmentedPacket);
533
534 NS_ASSERT (txParams.m_acknowledgment && txParams.m_acknowledgment->acknowledgmentTime != Time::Min ());
535 Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
536
537 // if the current frame is a fragment followed by another fragment, we have to
538 // update the Duration/ID to cover the next fragment and the corresponding Ack
539 if (header.IsMoreFragments ())
540 {
541 uint32_t payloadSize = size - header.GetSize () - WIFI_MAC_FCS_LENGTH;
542 uint32_t nextFragmentOffset = (header.GetFragmentNumber () + 1) * payloadSize;
543 uint32_t nextFragmentSize = std::min (fragmentedPacket->GetSize () - nextFragmentOffset,
544 payloadSize);
545 WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (header.GetAddr1 (),
546 txParams.m_txVector);
547
548 durationId += 2 * m_phy->GetSifs ()
549 + m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ())
550 + m_phy->CalculateTxDuration (nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand ());
551 }
552 return durationId;
553}
554
555Time
556FrameExchangeManager::GetRtsDurationId (const WifiTxVector& rtsTxVector, Time txDuration, Time response) const
557{
558 NS_LOG_FUNCTION (this << rtsTxVector << txDuration << response);
559
560 WifiTxVector ctsTxVector;
561 ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (m_self, rtsTxVector.GetMode ());
562
563 return m_phy->GetSifs ()
564 + m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ()) /* CTS */
565 + m_phy->GetSifs () + txDuration + response;
566}
567
568void
570{
571 NS_LOG_FUNCTION (this << &txParams);
572
573 NS_ASSERT (txParams.GetPsduInfoMap ().size () == 1);
574 Mac48Address receiver = txParams.GetPsduInfoMap ().begin ()->first;
575
576 WifiMacHeader rts;
578 rts.SetDsNotFrom ();
579 rts.SetDsNotTo ();
580 rts.SetNoRetry ();
581 rts.SetNoMoreFragments ();
582 rts.SetAddr1 (receiver);
583 rts.SetAddr2 (m_self);
584
585 NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
586 WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (txParams.m_protection.get ());
587
588 NS_ASSERT (txParams.m_txDuration != Time::Min ());
589 rts.SetDuration (GetRtsDurationId (rtsCtsProtection->rtsTxVector, txParams.m_txDuration,
590 txParams.m_acknowledgment->acknowledgmentTime));
591 Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (Create<Packet> (), rts);
592
593 // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
594 // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
595 // aRxPHYStartDelay equals the time to transmit the PHY header.
597 + m_phy->GetSifs ()
598 + m_phy->GetSlot ()
602 mpdu, rtsCtsProtection->rtsTxVector);
603 m_channelAccessManager->NotifyCtsTimeoutStartNow (timeout);
604
605 ForwardMpduDown (mpdu, rtsCtsProtection->rtsTxVector);
606}
607
608void
610 double rtsSnr)
611{
612 NS_LOG_FUNCTION (this << rtsHdr << ctsTxVector << rtsSnr);
613
614 WifiMacHeader cts;
616 cts.SetDsNotFrom ();
617 cts.SetDsNotTo ();
618 cts.SetNoMoreFragments ();
619 cts.SetNoRetry ();
620 cts.SetAddr1 (rtsHdr.GetAddr2 ());
621 Time duration = rtsHdr.GetDuration () - m_phy->GetSifs ()
622 - m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
623 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
624 if (duration.IsStrictlyNegative ())
625 {
626 duration = Seconds (0);
627 }
628 cts.SetDuration (duration);
629
630 Ptr<Packet> packet = Create<Packet> ();
631
632 SnrTag tag;
633 tag.Set (rtsSnr);
634 packet->AddPacketTag (tag);
635
636 // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
637 ForwardMpduDown (Create<WifiMacQueueItem> (packet, cts), ctsTxVector);
638}
639
640void
641FrameExchangeManager::SendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiMode rtsTxMode, double rtsSnr)
642{
643 NS_LOG_FUNCTION (this << rtsHdr << rtsTxMode << rtsSnr);
644
645 WifiTxVector ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (rtsHdr.GetAddr2 (), rtsTxMode);
646 DoSendCtsAfterRts (rtsHdr, ctsTxVector, rtsSnr);
647}
648
649Time
651 Time txDuration, Time response) const
652{
653 NS_LOG_FUNCTION (this << ctsTxVector << txDuration << response);
654
655 return m_phy->GetSifs () + txDuration + response;
656}
657
658void
660{
661 NS_LOG_FUNCTION (this << &txParams);
662
663 WifiMacHeader cts;
665 cts.SetDsNotFrom ();
666 cts.SetDsNotTo ();
667 cts.SetNoMoreFragments ();
668 cts.SetNoRetry ();
669 cts.SetAddr1 (m_self);
670
671 NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
672 WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (txParams.m_protection.get ());
673
674 NS_ASSERT (txParams.m_txDuration != Time::Min ());
675 cts.SetDuration (GetCtsToSelfDurationId (ctsToSelfProtection->ctsTxVector, txParams.m_txDuration,
676 txParams.m_acknowledgment->acknowledgmentTime));
677
678 ForwardMpduDown (Create<WifiMacQueueItem> (Create<Packet> (), cts), ctsToSelfProtection->ctsTxVector);
679
680 Time ctsDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsToSelfProtection->ctsTxVector,
681 m_phy->GetPhyBand ());
683}
684
685void
687 double dataSnr)
688{
689 NS_LOG_FUNCTION (this << hdr << dataTxVector << dataSnr);
690
691 WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (hdr.GetAddr2 (), dataTxVector);
692 WifiMacHeader ack;
694 ack.SetDsNotFrom ();
695 ack.SetDsNotTo ();
696 ack.SetNoRetry ();
697 ack.SetNoMoreFragments ();
698 ack.SetAddr1 (hdr.GetAddr2 ());
699 // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
700 // minus the time to transmit the Ack frame and its SIFS interval
701 Time duration = hdr.GetDuration () - m_phy->GetSifs ()
702 - m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ());
703 // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
704 if (duration.IsStrictlyNegative ())
705 {
706 duration = Seconds (0);
707 }
708 ack.SetDuration (duration);
709
710 Ptr<Packet> packet = Create<Packet> ();
711
712 SnrTag tag;
713 tag.Set (dataSnr);
714 packet->AddPacketTag (tag);
715
716 ForwardMpduDown (Create<WifiMacQueueItem> (packet, ack), ackTxVector);
717}
718
721{
722 NS_LOG_FUNCTION (this);
723 NS_ASSERT (m_mpdu->GetHeader ().IsMoreFragments ());
724
725 WifiMacHeader& hdr = m_mpdu->GetHeader ();
726 hdr.SetFragmentNumber (hdr.GetFragmentNumber () + 1);
727
728 uint32_t startOffset = hdr.GetFragmentNumber () * m_mpdu->GetPacketSize ();
729 uint32_t size = m_fragmentedPacket->GetSize () - startOffset;
730
731 if (size > m_mpdu->GetPacketSize ())
732 {
733 // this is not the last fragment
734 size = m_mpdu->GetPacketSize ();
735 hdr.SetMoreFragments ();
736 }
737 else
738 {
739 hdr.SetNoMoreFragments ();
740 }
741
742 return Create<WifiMacQueueItem> (m_fragmentedPacket->CreateFragment (startOffset, size), hdr);
743}
744
745void
747{
748 NS_LOG_FUNCTION (this);
749
750 // Upon a transmission success, a non-QoS station transmits the next fragment,
751 // if any, or releases the channel, otherwise
752 if (m_moreFragments)
753 {
754 NS_LOG_DEBUG ("Schedule transmission of next fragment in a SIFS");
756 m_moreFragments = false;
757 }
758 else
759 {
761 m_dcf = 0;
762 }
763}
764
765void
767{
768 NS_LOG_FUNCTION (this);
769 // A non-QoS station always releases the channel upon a transmission failure
771 m_dcf = 0;
772}
773
774void
776{
777 NS_LOG_FUNCTION (this << *mpdu << txVector);
778
779 m_mac->GetWifiRemoteStationManager ()->ReportDataFailed (mpdu);
780
781 if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
782 {
783 NS_LOG_DEBUG ("Missed Ack, discard MPDU");
785 // Dequeue the MPDU if it is stored in a queue
786 DequeueMpdu (mpdu);
787 m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
788 m_dcf->ResetCw ();
789 }
790 else
791 {
792 NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
793 mpdu->GetHeader ().SetRetry ();
796 }
797
798 m_mpdu = 0;
800}
801
802void
804{
805 NS_LOG_FUNCTION (this << *mpdu);
806}
807
808void
810{
811 NS_LOG_FUNCTION (this << *rts << txVector);
812
813 DoCtsTimeout (Create<WifiPsdu> (m_mpdu, true));
814 m_mpdu = nullptr;
815}
816
817void
819{
820 NS_LOG_FUNCTION (this << *psdu);
821
822 m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (psdu->GetHeader (0));
823
824 if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (*psdu->begin ()))
825 {
826 NS_LOG_DEBUG ("Missed CTS, discard MPDU(s)");
827 m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (psdu->GetHeader (0));
828 for (const auto& mpdu : *PeekPointer (psdu))
829 {
830 // Dequeue the MPDU if it is stored in a queue
831 DequeueMpdu (mpdu);
833 }
834 m_dcf->ResetCw ();
835 }
836 else
837 {
838 NS_LOG_DEBUG ("Missed CTS, retransmit MPDU(s)");
840 }
841 // Make the sequence numbers of the MPDUs available again if the MPDUs have never
842 // been transmitted, both in case the MPDUs have been discarded and in case the
843 // MPDUs have to be transmitted (because a new sequence number is assigned to
844 // MPDUs that have never been transmitted and are selected for transmission)
845 for (const auto& mpdu : *PeekPointer (psdu))
846 {
848 }
850}
851
852void
854{
855 NS_LOG_FUNCTION (this << *mpdu);
856
857 // the MPDU should be still in the DCF queue, unless it expired.
858 // If the MPDU has never been transmitted, it will be assigned a sequence
859 // number again the next time we try to transmit it. Therefore, we need to
860 // make its sequence number available again
861 if (!mpdu->GetHeader ().IsRetry ())
862 {
863 m_txMiddle->SetSequenceNumberFor (&mpdu->GetHeader ());
864 }
865}
866
867void
869{
870 NS_LOG_FUNCTION (this);
871
872 // For internal collisions occurring with the EDCA access method, the appropriate
873 // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
874 // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
875 // (Sec. 10.22.2.11.1 of 802.11-2016).
876 // We do not prepare the PSDU that the AC losing the internal collision would have
877 // sent. As an approximation, we consider the frame peeked from the queues of the AC.
878 Ptr<QosTxop> qosTxop = (txop->IsQosTxop () ? StaticCast<QosTxop> (txop) : nullptr);
879
880 Ptr<const WifiMacQueueItem> mpdu = (qosTxop != nullptr ? qosTxop->PeekNextMpdu ()
881 : txop->GetWifiMacQueue ()->Peek ());
882
883 if (mpdu != nullptr)
884 {
885 if (mpdu->GetHeader ().HasData ()
886 && !mpdu->GetHeader ().GetAddr1 ().IsGroup ())
887 {
888 m_mac->GetWifiRemoteStationManager ()->ReportDataFailed (mpdu);
889 }
890
891 if (!mpdu->GetHeader ().GetAddr1 ().IsGroup ()
892 && !m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
893 {
894 NS_LOG_DEBUG ("reset DCF");
895 m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
896 DequeueMpdu (mpdu);
898 txop->ResetCw ();
899 }
900 else
901 {
902 NS_LOG_DEBUG ("Update CW");
903 txop->UpdateFailedCw ();
904 }
905 }
906
907 txop->Txop::NotifyChannelReleased ();
908}
909
910void
912{
913 NS_LOG_DEBUG ("Switching channel. Cancelling MAC pending events");
914 m_mac->NotifyChannelSwitching ();
915 if (m_txTimer.IsRunning ())
916 {
917 // we were transmitting something before channel switching. Since we will
918 // not be able to receive the response, have the timer expire now, so that
919 // we perform the actions required in case of missing response
921 }
923}
924
925void
927{
928 NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
929 Reset ();
930}
931
932void
934{
935 NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
936 Reset ();
937}
938
939void
941 WifiTxVector txVector, std::vector<bool> perMpduStatus)
942{
943 NS_LOG_FUNCTION (this << psdu << rxSignalInfo << txVector << perMpduStatus.size ()
944 << std::all_of (perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
945
946 if (!perMpduStatus.empty ())
947 {
948 // for A-MPDUs, we get here only once
949 PreProcessFrame (psdu, txVector);
950 }
951
952 // ignore unicast frames that are not addressed to us
953 Mac48Address addr1 = psdu->GetAddr1 ();
954 if (!addr1.IsGroup () && addr1 != m_self)
955 {
956 if (m_promisc && psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsData ())
957 {
958 m_rxMiddle->Receive (*psdu->begin ());
959 }
960 return;
961 }
962
963 if (psdu->GetNMpdus () == 1)
964 {
965 // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
966 // then it must contain a single value which must be true (i.e., the MPDU
967 // has been correctly received)
968 NS_ASSERT (perMpduStatus.empty () || (perMpduStatus.size () == 1 && perMpduStatus[0]));
969 // Ack and CTS do not carry Addr2
970 if (!psdu->GetHeader (0).IsAck () && !psdu->GetHeader (0).IsCts ())
971 {
972 m_mac->GetWifiRemoteStationManager ()->ReportRxOk (psdu->GetHeader (0).GetAddr2 (),
973 rxSignalInfo, txVector);
974 }
975 ReceiveMpdu (*(psdu->begin ()), rxSignalInfo, txVector, perMpduStatus.empty ());
976 }
977 else
978 {
979 EndReceiveAmpdu (psdu, rxSignalInfo, txVector, perMpduStatus);
980 }
981}
982
983void
985{
986 NS_LOG_FUNCTION (this << psdu << txVector);
987
988 UpdateNav (psdu, txVector);
989}
990
991void
993{
994 NS_LOG_FUNCTION (this << psdu << txVector);
995
996 if (psdu->GetHeader (0).GetRawDuration () > 32767)
997 {
998 // When the contents of a received Duration/ID field, treated as an unsigned
999 // integer, are greater than 32 768, the contents are interpreted as appropriate
1000 // for the frame type and subtype or ignored if the receiving MAC entity does
1001 // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
1002 // sec. 10.27.3)
1003 return;
1004 }
1005
1006 Time duration = psdu->GetDuration ();
1007 NS_LOG_DEBUG ("Duration/ID=" << duration);
1008
1009 if (psdu->GetAddr1 () == m_self)
1010 {
1011 // When the received frame’s RA is equal to the STA’s own MAC address, the STA
1012 // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
1013 return;
1014 }
1015
1016 // For all other received frames the STA shall update its NAV when the received
1017 // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
1018 Time navEnd = Simulator::Now () + duration;
1019 if (navEnd > m_navEnd)
1020 {
1021 m_navEnd = navEnd;
1022 NS_LOG_DEBUG ("Updated NAV=" << m_navEnd);
1023
1024 // A STA that used information from an RTS frame as the most recent basis to update
1025 // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
1026 // primitive is received from the PHY during a NAVTimeout period starting when the
1027 // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
1028 // the RTS frame. NAVTimeout period is equal to:
1029 // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
1030 // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
1031 // rate at which the RTS frame used for the most recent NAV update was received
1032 // (IEEE 802.11-2016 sec. 10.3.2.4)
1033 if (psdu->GetHeader (0).IsRts ())
1034 {
1035 Time navResetDelay = 2 * m_phy->GetSifs ()
1037 m_phy->GetPhyBand ())
1039 + 2 * m_phy->GetSlot ();
1041 }
1042 }
1043 NS_LOG_DEBUG ("Current NAV=" << m_navEnd);
1044
1045 m_channelAccessManager->NotifyNavStartNow (duration);
1046}
1047
1048void
1050{
1051 NS_LOG_FUNCTION (this);
1053 m_channelAccessManager->NotifyNavResetNow (Seconds (0));
1054}
1055
1056void
1058 const WifiTxVector& txVector, bool inAmpdu)
1059{
1060 NS_LOG_FUNCTION (this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1061 // The received MPDU is either broadcast or addressed to this station
1062 NS_ASSERT (mpdu->GetHeader ().GetAddr1 ().IsGroup ()
1063 || mpdu->GetHeader ().GetAddr1 () == m_self);
1064
1065 double rxSnr = rxSignalInfo.snr;
1066 const WifiMacHeader& hdr = mpdu->GetHeader ();
1067
1068 if (hdr.IsCtl ())
1069 {
1070 if (hdr.IsRts ())
1071 {
1072 NS_ABORT_MSG_IF (inAmpdu, "Received RTS as part of an A-MPDU");
1073
1074 // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1075 // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1076 // - Otherwise, the STA shall not respond with a CTS frame
1077 // (IEEE 802.11-2016 sec. 10.3.2.7)
1078 if (m_navEnd <= Simulator::Now ())
1079 {
1080 NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
1082 this, hdr, txVector.GetMode (), rxSnr);
1083 }
1084 else
1085 {
1086 NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
1087 }
1088 }
1089 else if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS
1090 && m_mpdu != 0)
1091 {
1092 NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU");
1093 NS_ASSERT (hdr.GetAddr1 () == m_self);
1094
1095 Mac48Address sender = m_mpdu->GetHeader ().GetAddr1 ();
1096 NS_LOG_DEBUG ("Received CTS from=" << sender);
1097
1098 SnrTag tag;
1099 mpdu->GetPacket ()->PeekPacketTag (tag);
1100 m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector);
1101 m_mac->GetWifiRemoteStationManager ()->ReportRtsOk (m_mpdu->GetHeader (),
1102 rxSnr, txVector.GetMode (), tag.Get ());
1103
1104 m_txTimer.Cancel ();
1105 m_channelAccessManager->NotifyCtsTimeoutResetNow ();
1107 }
1108 else if (hdr.IsAck () && m_mpdu != 0 && m_txTimer.IsRunning ()
1110 {
1111 NS_ASSERT (hdr.GetAddr1 () == m_self);
1112 SnrTag tag;
1113 mpdu->GetPacket ()->PeekPacketTag (tag);
1114 ReceivedNormalAck (m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ());
1115 m_mpdu = 0;
1116 }
1117 }
1118 else if (hdr.IsMgt ())
1119 {
1120 NS_ABORT_MSG_IF (inAmpdu, "Received management frame as part of an A-MPDU");
1121
1122 if (hdr.IsBeacon () || hdr.IsProbeResp ())
1123 {
1124 // Apply SNR tag for beacon quality measurements
1125 SnrTag tag;
1126 tag.Set (rxSnr);
1127 Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
1128 packet->AddPacketTag (tag);
1129 mpdu = Create<WifiMacQueueItem> (packet, hdr);
1130 }
1131
1132 if (hdr.GetAddr1 () == m_self)
1133 {
1134 NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1136 this, hdr, txVector, rxSnr);
1137 }
1138
1139 m_rxMiddle->Receive (mpdu);
1140 }
1141 else if (hdr.IsData () && !hdr.IsQosData ())
1142 {
1143 if (hdr.GetAddr1 () == m_self)
1144 {
1145 NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1147 this, hdr, txVector, rxSnr);
1148 }
1149
1150 m_rxMiddle->Receive (mpdu);
1151 }
1152}
1153
1154void
1156 const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo,
1157 double snr)
1158{
1159 Mac48Address sender = mpdu->GetHeader ().GetAddr1 ();
1160 NS_LOG_DEBUG ("Received ACK from=" << sender);
1161
1163
1164 // When fragmentation is used, only update manager when the last fragment is acknowledged
1165 if (!mpdu->GetHeader ().IsMoreFragments ())
1166 {
1167 m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxInfo, ackTxVector);
1168 m_mac->GetWifiRemoteStationManager ()->ReportDataOk (mpdu, rxInfo.snr, ackTxVector.GetMode (),
1169 snr, txVector);
1170 }
1171 // cancel the timer
1172 m_txTimer.Cancel ();
1173 m_channelAccessManager->NotifyAckTimeoutResetNow ();
1174
1175 // The CW shall be reset to aCWmin after every successful attempt to transmit
1176 // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1177 m_dcf->ResetCw ();
1178
1179 if (mpdu->GetHeader ().IsMoreFragments ())
1180 {
1181 // replace the current fragment with the next one
1182 m_dcf->GetWifiMacQueue ()->Replace (mpdu, GetNextFragment ());
1183 m_moreFragments = true;
1184 }
1185 else
1186 {
1187 // the MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1188 DequeueMpdu (mpdu);
1189 }
1190
1192}
1193
1194void
1196{
1197 NS_LOG_FUNCTION (this << *mpdu);
1198
1199 // inform the MAC that the transmission was successful
1201 {
1202 m_ackedMpduCallback (mpdu);
1203 }
1204}
1205
1206void
1208 const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus)
1209{
1210 NS_ASSERT_MSG (false, "A non-QoS station should not receive an A-MPDU");
1211}
1212
1213} //namespace ns3
#define min(a, b)
Definition: 80211b.c:42
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
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
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...
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.
virtual void CtsTimeout(Ptr< WifiMacQueueItem > rts, const WifiTxVector &txVector)
Called when the CTS timeout expires.
Ptr< WifiMac > m_mac
the MAC layer on this station
virtual void ForwardMpduDown(Ptr< WifiMacQueueItem > mpdu, WifiTxVector &txVector)
Forward an MPDU down to the PHY layer.
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.
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
WifiTxTimer m_txTimer
the timer set upon frame transmission
void SendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiMode rtsTxMode, double rtsSnr)
Send CTS after receiving RTS.
virtual void NotifyReceivedNormalAck(Ptr< WifiMacQueueItem > mpdu)
Notify other components that an MPDU was acknowledged.
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 ReceivedNormalAck(Ptr< WifiMacQueueItem > mpdu, const WifiTxVector &txVector, const WifiTxVector &ackTxVector, const RxSignalInfo &rxInfo, double snr)
Perform the actions needed when a Normal Ack is received.
Ptr< WifiProtectionManager > m_protectionManager
Protection manager.
Ptr< WifiMacQueueItem > GetFirstFragmentIfNeeded(Ptr< WifiMacQueueItem > mpdu)
Fragment the given MPDU if needed.
void SendRts(const WifiTxParameters &txParams)
Send RTS to begin RTS-CTS-Data-Ack transaction.
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 NotifyPacketDiscarded(Ptr< const WifiMacQueueItem > mpdu)
Pass the given MPDU, discarded because of the max retry limit was reached, to the MPDU dropped callba...
virtual void RetransmitMpduAfterMissedAck(Ptr< WifiMacQueueItem > mpdu) const
Retransmit an MPDU that was not acknowledged.
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.
void SendMpduWithProtection(Ptr< WifiMacQueueItem > mpdu, WifiTxParameters &txParams)
Send an MPDU with the given TX parameters (with the specified protection).
virtual bool StartTransmission(Ptr< Txop > dcf)
Request the FrameExchangeManager to start a frame exchange sequence.
Ptr< WifiMacQueueItem > m_mpdu
the MPDU being transmitted
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< WifiMacQueueItem > GetNextFragment(void)
Get the next fragment of the current MSDU.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
Ptr< Txop > m_dcf
the DCF/EDCAF that gained channel access
virtual void ReceiveMpdu(Ptr< WifiMacQueueItem > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu)
This method handles the reception of an MPDU (possibly included in an A-MPDU)
Ptr< WifiPhy > m_phy
the PHY layer on this station
virtual void TransmissionFailed(void)
Take necessary actions upon a transmission failure.
Ptr< WifiAckManager > GetAckManager(void) const
Get the Acknowledgment Manager used by this node.
virtual void ReleaseSequenceNumber(Ptr< WifiMacQueueItem > mpdu) const
Make the sequence number of the given MPDU available again if the MPDU has never been transmitted.
void Receive(Ptr< 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...
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 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 ...
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 DequeueMpdu(Ptr< const WifiMacQueueItem > mpdu)
Dequeue the given MPDU from the queue in which it is stored.
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
bool m_promisc
Flag if the device is operating in promiscuous mode.
virtual void NormalAckTimeout(Ptr< WifiMacQueueItem > mpdu, const WifiTxVector &txVector)
Called when the Ack timeout expires.
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 uint32_t GetPsduSize(Ptr< const WifiMacQueueItem > mpdu, const WifiTxVector &txVector) const
Get the size in bytes of the given MPDU, which is to be transmitted with the given TXVECTOR.
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:74
Ptr< const WifiMacQueueItem > PeekNextMpdu(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMacQueueItem > item=nullptr)
Peek the next frame to transmit to the given receiver and of the given TID from the EDCA queue.
Definition: qos-txop.cc:357
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:587
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:103
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:332
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:273
@ US
microsecond
Definition: nstime.h:116
bool IsStrictlyNegative(void) const
Exactly equivalent to t < 0.
Definition: nstime.h:324
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:432
void UpdateFailedCw(void)
Update the value of the CW variable to take into account a transmission failure.
Definition: txop.cc:199
virtual void NotifyChannelReleased(void)
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: txop.cc:355
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:154
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:412
virtual void NotifyChannelAccessed(Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted for the given amoun...
Definition: txop.cc:348
void ResetCw(void)
Update the value of the CW variable to take into account a transmission success or a transmission abo...
Definition: txop.cc:191
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< WifiMacQueueItem > 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.
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:1485
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:870
Time GetSlot(void) const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:671
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1306
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:659
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:384
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1300
Time GetDuration(void) const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition: wifi-psdu.cc:141
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:325
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:319
Mac48Address GetAddr1(void) const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:111
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 WifiMacQueueItem > 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, Ts... > MakeNullCallback(void)
Definition: callback.h:1688
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octects of the IEEE 802.11 MAC FCS field.
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
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition: wifi-mac.h:69
mac
Definition: third.py:96
phy
Definition: third.py:93
ns3::Time timeout
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double snr
SNR in linear scale.
Definition: phy-entity.h:68
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.