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"
23 #include "frame-exchange-manager.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 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("FrameExchangeManager");
40 
41 NS_OBJECT_ENSURE_REGISTERED (FrameExchangeManager);
42 
43 TypeId
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 
67 void
69 {
70  NS_LOG_FUNCTION (this);
71  m_txTimer.Cancel ();
73  {
75  }
77  m_mpdu = 0;
78  m_txParams.Clear ();
79  m_dcf = 0;
80 }
81 
82 void
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 
103 void
105 {
106  NS_LOG_FUNCTION (this << protectionManager);
107  m_protectionManager = protectionManager;
108 }
109 
112 {
113  return m_protectionManager;
114 }
115 
116 void
118 {
119  NS_LOG_FUNCTION (this << ackManager);
120  m_ackManager = ackManager;
121 }
122 
125 {
126  return m_ackManager;
127 }
128 
129 void
131 {
132  NS_LOG_FUNCTION (this << mac);
133  m_mac = mac;
134 }
135 
136 void
138 {
139  NS_LOG_FUNCTION (this << txMiddle);
140  m_txMiddle = txMiddle;
141 }
142 
143 void
145 {
146  NS_LOG_FUNCTION (this << rxMiddle);
147  m_rxMiddle = rxMiddle;
148 }
149 
150 void
152 {
153  NS_LOG_FUNCTION (this << channelAccessManager);
154  m_channelAccessManager = channelAccessManager;
155 }
156 
157 void
159 {
160  NS_LOG_FUNCTION (this << phy);
161  m_phy = phy;
162  m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin",
165 }
166 
167 void
169 {
170  m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
173  m_phy = 0;
174 }
175 
176 void
178 {
179  NS_LOG_FUNCTION (this << address);
180  m_self = address;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << bssid);
187  m_bssid = bssid;
188 }
189 
190 void
192 {
193  NS_LOG_FUNCTION (this << &callback);
194  m_droppedMpduCallback = callback;
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this << &callback);
201  m_ackedMpduCallback = callback;
202 }
203 
204 void
206 {
207  m_promisc = true;
208 }
209 
210 bool
212 {
213  return m_promisc;
214 }
215 
216 const WifiTxTimer&
218 {
219  return m_txTimer;
220 }
221 
222 void
224 {
226  {
228  }
229 }
230 
231 void
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 
252  if (m_navResetEvent.IsRunning ())
253  {
255  }
256 }
257 
258 bool
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 ()->GetQueueIteratorPairs ().front ().it;
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  // dequeue the MSDU
332  queueIt.queue->Dequeue (queueIt.it);
333  // create the first fragment
334  mpdu->GetHeader ().SetMoreFragments ();
335  Ptr<Packet> fragment = m_fragmentedPacket->CreateFragment (0, m_mac->GetWifiRemoteStationManager ()->GetFragmentSize (mpdu, 0));
336  // enqueue the first fragment
337  Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (fragment, mpdu->GetHeader (), mpdu->GetTimeStamp ());
338  queueIt.queue->PushFront (item);
339  return item;
340  }
341  return mpdu;
342 }
343 
344 void
346 {
347  NS_LOG_FUNCTION (this << *mpdu << &txParams);
348 
349  m_mpdu = mpdu;
350  m_txParams = std::move (txParams);
351 
352  // If protection is required, the MPDU must be stored in some queue because
353  // it is not put back in a queue if the RTS/CTS exchange fails
355  || m_mpdu->GetHeader ().IsCtl ()
356  || m_mpdu->IsQueued ());
357 
358  // Make sure that the acknowledgment time has been computed, so that SendRts()
359  // and SendCtsToSelf() can reuse this value.
361 
362  if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min ())
363  {
365  }
366 
367  // Set QoS Ack policy if this is a QoS data frame
369 
370  switch (m_txParams.m_protection->method)
371  {
374  break;
377  break;
379  SendMpdu ();
380  break;
381  default:
382  NS_ABORT_MSG ("Unknown protection type");
383  }
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION (this);
390 
392 
394 
396  {
398  }
400  {
403 
404  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
405  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
406  // aRxPHYStartDelay equals the time to transmit the PHY header.
407  WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (m_txParams.m_acknowledgment.get ());
408 
409  Time timeout = txDuration
410  + m_phy->GetSifs ()
411  + m_phy->GetSlot ()
412  + m_phy->CalculatePhyPreambleAndHeaderDuration (normalAcknowledgment->ackTxVector);
415  this, m_mpdu, m_txParams.m_txVector);
416  m_channelAccessManager->NotifyAckTimeoutStartNow (timeout);
417  }
418  else
419  {
420  NS_ABORT_MSG ("Unable to handle the selected acknowledgment method ("
421  << m_txParams.m_acknowledgment.get () << ")");
422  }
423 
424  // transmit the MPDU
426 
428  {
429  // we are done with frames that do not require acknowledgment
430  m_mpdu = 0;
431  }
432 }
433 
434 void
436 {
437  NS_LOG_FUNCTION (this << *mpdu << txVector);
438 
439  // The MPDU is about to be transmitted, we can now dequeue it if it is stored in a queue
440  DequeueMpdu (mpdu);
441 
442  m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
443 }
444 
445 void
447 {
448  NS_LOG_DEBUG (this << *mpdu);
449 
450  if (mpdu->IsQueued ())
451  {
453  NS_ASSERT (*queueIt.it == mpdu);
454  queueIt.queue->Dequeue (queueIt.it);
455  }
456 }
457 
458 void
460 {
461  NS_LOG_FUNCTION (this << protection);
462  NS_ASSERT (protection != nullptr);
463 
464  if (protection->method == WifiProtection::NONE)
465  {
466  protection->protectionTime = Seconds (0);
467  }
468  else if (protection->method == WifiProtection::RTS_CTS)
469  {
470  WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (protection);
471  rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration (GetRtsSize (), rtsCtsProtection->rtsTxVector,
472  m_phy->GetPhyBand ())
473  + m_phy->CalculateTxDuration (GetCtsSize (), rtsCtsProtection->ctsTxVector,
474  m_phy->GetPhyBand ())
475  + 2 * m_phy->GetSifs ();
476  }
477  else if (protection->method == WifiProtection::CTS_TO_SELF)
478  {
479  WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (protection);
480  ctsToSelfProtection->protectionTime = m_phy->CalculateTxDuration (GetCtsSize (),
481  ctsToSelfProtection->ctsTxVector,
482  m_phy->GetPhyBand ())
483  + m_phy->GetSifs ();
484  }
485 }
486 
487 void
489 {
490  NS_LOG_FUNCTION (this << acknowledgment);
491  NS_ASSERT (acknowledgment != nullptr);
492 
493  if (acknowledgment->method == WifiAcknowledgment::NONE)
494  {
495  acknowledgment->acknowledgmentTime = Seconds (0);
496  }
497  else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
498  {
499  WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (acknowledgment);
500  normalAcknowledgment->acknowledgmentTime = m_phy->GetSifs ()
502  normalAcknowledgment->ackTxVector,
503  m_phy->GetPhyBand ());
504  }
505 }
506 
507 Time
508 FrameExchangeManager::GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
509  const WifiTxParameters& txParams) const
510 {
511  return m_phy->CalculateTxDuration (ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand ());
512 }
513 
514 void
516 {
517  txParams.m_txDuration = GetTxDuration (txParams.GetSize (receiver), receiver, txParams);
518 }
519 
520 Time
522  const WifiTxParameters& txParams,
523  Ptr<Packet> fragmentedPacket) const
524 {
525  NS_LOG_FUNCTION (this << header << size << &txParams << fragmentedPacket);
526 
527  NS_ASSERT (txParams.m_acknowledgment && txParams.m_acknowledgment->acknowledgmentTime != Time::Min ());
528  Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
529 
530  // if the current frame is a fragment followed by another fragment, we have to
531  // update the Duration/ID to cover the next fragment and the corresponding Ack
532  if (header.IsMoreFragments ())
533  {
534  uint32_t payloadSize = size - header.GetSize () - WIFI_MAC_FCS_LENGTH;
535  uint32_t nextFragmentOffset = (header.GetFragmentNumber () + 1) * payloadSize;
536  uint32_t nextFragmentSize = std::min (fragmentedPacket->GetSize () - nextFragmentOffset,
537  payloadSize);
538  WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (header.GetAddr1 (),
539  txParams.m_txVector);
540 
541  durationId += 2 * m_phy->GetSifs ()
542  + m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ())
543  + m_phy->CalculateTxDuration (nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand ());
544  }
545  return durationId;
546 }
547 
548 Time
549 FrameExchangeManager::GetRtsDurationId (const WifiTxVector& rtsTxVector, Time txDuration, Time response) const
550 {
551  NS_LOG_FUNCTION (this << rtsTxVector << txDuration << response);
552 
553  WifiTxVector ctsTxVector;
554  ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (m_self, rtsTxVector.GetMode ());
555 
556  return m_phy->GetSifs ()
557  + m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ()) /* CTS */
558  + m_phy->GetSifs () + txDuration + response;
559 }
560 
561 void
563 {
564  NS_LOG_FUNCTION (this << &txParams);
565 
566  NS_ASSERT (txParams.GetPsduInfoMap ().size () == 1);
567  Mac48Address receiver = txParams.GetPsduInfoMap ().begin ()->first;
568 
569  WifiMacHeader rts;
571  rts.SetDsNotFrom ();
572  rts.SetDsNotTo ();
573  rts.SetNoRetry ();
574  rts.SetNoMoreFragments ();
575  rts.SetAddr1 (receiver);
576  rts.SetAddr2 (m_self);
577 
578  NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
579  WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (txParams.m_protection.get ());
580 
581  NS_ASSERT (txParams.m_txDuration != Time::Min ());
582  rts.SetDuration (GetRtsDurationId (rtsCtsProtection->rtsTxVector, txParams.m_txDuration,
583  txParams.m_acknowledgment->acknowledgmentTime));
584  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (Create<Packet> (), rts);
585 
586  // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
587  // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
588  // aRxPHYStartDelay equals the time to transmit the PHY header.
590  + m_phy->GetSifs ()
591  + m_phy->GetSlot ()
595  mpdu, rtsCtsProtection->rtsTxVector);
596  m_channelAccessManager->NotifyCtsTimeoutStartNow (timeout);
597 
598  ForwardMpduDown (mpdu, rtsCtsProtection->rtsTxVector);
599 }
600 
601 void
603  double rtsSnr)
604 {
605  NS_LOG_FUNCTION (this << rtsHdr << ctsTxVector << rtsSnr);
606 
607  WifiMacHeader cts;
609  cts.SetDsNotFrom ();
610  cts.SetDsNotTo ();
611  cts.SetNoMoreFragments ();
612  cts.SetNoRetry ();
613  cts.SetAddr1 (rtsHdr.GetAddr2 ());
614  Time duration = rtsHdr.GetDuration () - m_phy->GetSifs ()
615  - m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
616  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
617  if (duration.IsStrictlyNegative ())
618  {
619  duration = Seconds (0);
620  }
621  cts.SetDuration (duration);
622 
623  Ptr<Packet> packet = Create<Packet> ();
624 
625  SnrTag tag;
626  tag.Set (rtsSnr);
627  packet->AddPacketTag (tag);
628 
629  // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
630  ForwardMpduDown (Create<WifiMacQueueItem> (packet, cts), ctsTxVector);
631 }
632 
633 void
634 FrameExchangeManager::SendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiMode rtsTxMode, double rtsSnr)
635 {
636  NS_LOG_FUNCTION (this << rtsHdr << rtsTxMode << rtsSnr);
637 
638  WifiTxVector ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (rtsHdr.GetAddr2 (), rtsTxMode);
639  DoSendCtsAfterRts (rtsHdr, ctsTxVector, rtsSnr);
640 }
641 
642 Time
644  Time txDuration, Time response) const
645 {
646  NS_LOG_FUNCTION (this << ctsTxVector << txDuration << response);
647 
648  return m_phy->GetSifs () + txDuration + response;
649 }
650 
651 void
653 {
654  NS_LOG_FUNCTION (this << &txParams);
655 
656  WifiMacHeader cts;
658  cts.SetDsNotFrom ();
659  cts.SetDsNotTo ();
660  cts.SetNoMoreFragments ();
661  cts.SetNoRetry ();
662  cts.SetAddr1 (m_self);
663 
664  NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
665  WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (txParams.m_protection.get ());
666 
667  NS_ASSERT (txParams.m_txDuration != Time::Min ());
668  cts.SetDuration (GetCtsToSelfDurationId (ctsToSelfProtection->ctsTxVector, txParams.m_txDuration,
669  txParams.m_acknowledgment->acknowledgmentTime));
670 
671  ForwardMpduDown (Create<WifiMacQueueItem> (Create<Packet> (), cts), ctsToSelfProtection->ctsTxVector);
672 
673  Time ctsDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsToSelfProtection->ctsTxVector,
674  m_phy->GetPhyBand ());
676 }
677 
678 void
680  double dataSnr)
681 {
682  NS_LOG_FUNCTION (this << hdr << dataTxVector << dataSnr);
683 
684  WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (hdr.GetAddr2 (), dataTxVector);
685  WifiMacHeader ack;
687  ack.SetDsNotFrom ();
688  ack.SetDsNotTo ();
689  ack.SetNoRetry ();
690  ack.SetNoMoreFragments ();
691  ack.SetAddr1 (hdr.GetAddr2 ());
692  // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
693  // minus the time to transmit the Ack frame and its SIFS interval
694  Time duration = hdr.GetDuration () - m_phy->GetSifs ()
695  - m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ());
696  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
697  if (duration.IsStrictlyNegative ())
698  {
699  duration = Seconds (0);
700  }
701  ack.SetDuration (duration);
702 
703  Ptr<Packet> packet = Create<Packet> ();
704 
705  SnrTag tag;
706  tag.Set (dataSnr);
707  packet->AddPacketTag (tag);
708 
709  ForwardMpduDown (Create<WifiMacQueueItem> (packet, ack), ackTxVector);
710 }
711 
714 {
715  NS_LOG_FUNCTION (this);
717 
718  WifiMacHeader& hdr = m_mpdu->GetHeader ();
719  hdr.SetFragmentNumber (hdr.GetFragmentNumber () + 1);
720 
721  uint32_t startOffset = hdr.GetFragmentNumber () * m_mpdu->GetPacketSize ();
722  uint32_t size = m_fragmentedPacket->GetSize () - startOffset;
723 
724  if (size > m_mpdu->GetPacketSize ())
725  {
726  // this is not the last fragment
727  size = m_mpdu->GetPacketSize ();
728  hdr.SetMoreFragments ();
729  }
730  else
731  {
732  hdr.SetNoMoreFragments ();
733  }
734 
735  return Create<WifiMacQueueItem> (m_fragmentedPacket->CreateFragment (startOffset, size), hdr);
736 }
737 
738 void
740 {
741  NS_LOG_FUNCTION (this);
742 
743  // Upon a transmission success, a non-QoS station transmits the next fragment,
744  // if any, or releases the channel, otherwise
745  if (m_moreFragments)
746  {
747  NS_LOG_DEBUG ("Schedule transmission of next fragment in a SIFS");
749  m_moreFragments = false;
750  }
751  else
752  {
754  m_dcf = 0;
755  }
756 }
757 
758 void
760 {
761  NS_LOG_FUNCTION (this);
762  // A non-QoS station always releases the channel upon a transmission failure
764  m_dcf = 0;
765 }
766 
767 void
769 {
770  NS_LOG_FUNCTION (this << *mpdu << txVector);
771 
772  m_mac->GetWifiRemoteStationManager ()->ReportDataFailed (mpdu);
773 
774  if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
775  {
776  NS_LOG_DEBUG ("Missed Ack, discard MPDU");
777  NotifyPacketDiscarded (mpdu);
778  m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
779  m_dcf->ResetCw ();
780  }
781  else
782  {
783  NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
784  mpdu->GetHeader ().SetRetry ();
786  m_dcf->UpdateFailedCw ();
787  }
788 
789  m_mpdu = 0;
791 }
792 
793 void
795 {
796  NS_LOG_FUNCTION (this << *mpdu);
797 
798  // insert the MPDU in the DCF queue again
799  m_dcf->GetWifiMacQueue ()->PushFront (mpdu);
800 }
801 
802 void
804 {
805  NS_LOG_FUNCTION (this << *rts << txVector);
806 
807  m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_mpdu->GetHeader ());
808 
809  if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (m_mpdu))
810  {
811  NS_LOG_DEBUG ("Missed CTS, discard MPDU");
812  // Dequeue the MPDU if it is stored in a queue
815  m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (m_mpdu->GetHeader ());
816  m_dcf->ResetCw ();
817  }
818  else
819  {
820  NS_LOG_DEBUG ("Missed CTS, retransmit RTS");
822  m_dcf->UpdateFailedCw ();
823  }
824  m_mpdu = 0;
826 }
827 
828 void
830 {
831  NS_LOG_FUNCTION (this << *mpdu);
832 
833  // the MPDU should be still in the DCF queue, unless it expired.
834  // If the MPDU has never been transmitted, it will be assigned a sequence
835  // number again the next time we try to transmit it. Therefore, we need to
836  // make its sequence number available again
837  if (!mpdu->GetHeader ().IsRetry ())
838  {
839  m_txMiddle->SetSequenceNumberFor (&mpdu->GetHeader ());
840  }
841 }
842 
843 void
845 {
846  NS_LOG_DEBUG ("Switching channel. Cancelling MAC pending events");
847  m_mac->GetWifiRemoteStationManager ()->Reset ();
848  Reset ();
849 }
850 
851 void
853 {
854  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
855  Reset ();
856 }
857 
858 void
860 {
861  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
862  Reset ();
863 }
864 
865 void
867  WifiTxVector txVector, std::vector<bool> perMpduStatus)
868 {
869  NS_LOG_FUNCTION (this << psdu << rxSignalInfo << txVector << perMpduStatus.size ()
870  << std::all_of (perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
871 
872  if (!perMpduStatus.empty ())
873  {
874  // for A-MPDUs, we get here only once
875  PreProcessFrame (psdu, txVector);
876  }
877 
878  // ignore unicast frames that are not addressed to us
879  Mac48Address addr1 = psdu->GetAddr1 ();
880  if (!addr1.IsGroup () && addr1 != m_self)
881  {
882  if (m_promisc && psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsData ())
883  {
884  m_rxMiddle->Receive (*psdu->begin ());
885  }
886  return;
887  }
888 
889  if (psdu->GetNMpdus () == 1)
890  {
891  // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
892  // then it must contain a single value which must be true (i.e., the MPDU
893  // has been correctly received)
894  NS_ASSERT (perMpduStatus.empty () || (perMpduStatus.size () == 1 && perMpduStatus[0]));
895  // Ack and CTS do not carry Addr2
896  if (!psdu->GetHeader (0).IsAck () && !psdu->GetHeader (0).IsCts ())
897  {
898  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (psdu->GetHeader (0).GetAddr2 (),
899  rxSignalInfo, txVector);
900  }
901  ReceiveMpdu (*(psdu->begin ()), rxSignalInfo, txVector, perMpduStatus.empty ());
902  }
903  else
904  {
905  EndReceiveAmpdu (psdu, rxSignalInfo, txVector, perMpduStatus);
906  }
907 }
908 
909 void
911 {
912  NS_LOG_FUNCTION (this << psdu << txVector);
913 
914  UpdateNav (psdu, txVector);
915 }
916 
917 void
919 {
920  NS_LOG_FUNCTION (this << psdu << txVector);
921 
922  if (psdu->GetHeader (0).GetRawDuration () > 32767)
923  {
924  // When the contents of a received Duration/ID field, treated as an unsigned
925  // integer, are greater than 32 768, the contents are interpreted as appropriate
926  // for the frame type and subtype or ignored if the receiving MAC entity does
927  // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
928  // sec. 10.27.3)
929  return;
930  }
931 
932  Time duration = psdu->GetDuration ();
933  NS_LOG_DEBUG ("Duration/ID=" << duration);
934 
935  if (psdu->GetAddr1 () == m_self)
936  {
937  // When the received frame’s RA is equal to the STA’s own MAC address, the STA
938  // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
939  return;
940  }
941 
942  // For all other received frames the STA shall update its NAV when the received
943  // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
944  Time navEnd = Simulator::Now () + duration;
945  if (navEnd > m_navEnd)
946  {
947  m_navEnd = navEnd;
948  NS_LOG_DEBUG ("Updated NAV=" << m_navEnd);
949 
950  // A STA that used information from an RTS frame as the most recent basis to update
951  // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
952  // primitive is received from the PHY during a NAVTimeout period starting when the
953  // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
954  // the RTS frame. NAVTimeout period is equal to:
955  // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
956  // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
957  // rate at which the RTS frame used for the most recent NAV update was received
958  // (IEEE 802.11-2016 sec. 10.3.2.4)
959  if (psdu->GetHeader (0).IsRts ())
960  {
961  Time navResetDelay = 2 * m_phy->GetSifs ()
963  m_phy->GetPhyBand ())
965  + 2 * m_phy->GetSlot ();
967  }
968  }
969  NS_LOG_DEBUG ("Current NAV=" << m_navEnd);
970 
971  m_channelAccessManager->NotifyNavStartNow (duration);
972 }
973 
974 void
976 {
977  NS_LOG_FUNCTION (this);
979  m_channelAccessManager->NotifyNavResetNow (Seconds (0));
980 }
981 
982 void
984  const WifiTxVector& txVector, bool inAmpdu)
985 {
986  NS_LOG_FUNCTION (this << *mpdu << rxSignalInfo << txVector << inAmpdu);
987  // The received MPDU is either broadcast or addressed to this station
988  NS_ASSERT (mpdu->GetHeader ().GetAddr1 ().IsGroup ()
989  || mpdu->GetHeader ().GetAddr1 () == m_self);
990 
991  double rxSnr = rxSignalInfo.snr;
992  const WifiMacHeader& hdr = mpdu->GetHeader ();
993 
994  if (hdr.IsCtl ())
995  {
996  if (hdr.IsRts ())
997  {
998  NS_ABORT_MSG_IF (inAmpdu, "Received RTS as part of an A-MPDU");
999 
1000  // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1001  // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1002  // - Otherwise, the STA shall not respond with a CTS frame
1003  // (IEEE 802.11-2016 sec. 10.3.2.7)
1004  if (m_navEnd <= Simulator::Now ())
1005  {
1006  NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
1008  this, hdr, txVector.GetMode (), rxSnr);
1009  }
1010  else
1011  {
1012  NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
1013  }
1014  }
1015  else if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS
1016  && m_mpdu != 0)
1017  {
1018  NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU");
1019  NS_ASSERT (hdr.GetAddr1 () == m_self);
1020 
1021  Mac48Address sender = m_mpdu->GetHeader ().GetAddr1 ();
1022  NS_LOG_DEBUG ("Received CTS from=" << sender);
1023 
1024  SnrTag tag;
1025  mpdu->GetPacket ()->PeekPacketTag (tag);
1026  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector);
1027  m_mac->GetWifiRemoteStationManager ()->ReportRtsOk (m_mpdu->GetHeader (),
1028  rxSnr, txVector.GetMode (), tag.Get ());
1029 
1030  m_txTimer.Cancel ();
1031  m_channelAccessManager->NotifyCtsTimeoutResetNow ();
1033  }
1034  else if (hdr.IsAck () && m_mpdu != 0 && m_txTimer.IsRunning ()
1036  {
1037  NS_ASSERT (hdr.GetAddr1 () == m_self);
1038  SnrTag tag;
1039  mpdu->GetPacket ()->PeekPacketTag (tag);
1040  ReceivedNormalAck (m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ());
1041  m_mpdu = 0;
1042  }
1043  }
1044  else if (hdr.IsMgt ())
1045  {
1046  NS_ABORT_MSG_IF (inAmpdu, "Received management frame as part of an A-MPDU");
1047 
1048  if (hdr.IsBeacon () || hdr.IsProbeResp ())
1049  {
1050  // Apply SNR tag for beacon quality measurements
1051  SnrTag tag;
1052  tag.Set (rxSnr);
1053  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
1054  packet->AddPacketTag (tag);
1055  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1056  }
1057 
1058  if (hdr.GetAddr1 () == m_self)
1059  {
1060  NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1062  this, hdr, txVector, rxSnr);
1063  }
1064 
1065  m_rxMiddle->Receive (mpdu);
1066  }
1067  else if (hdr.IsData () && !hdr.IsQosData ())
1068  {
1069  if (hdr.GetAddr1 () == m_self)
1070  {
1071  NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1073  this, hdr, txVector, rxSnr);
1074  }
1075 
1076  m_rxMiddle->Receive (mpdu);
1077  }
1078 }
1079 
1080 void
1082  const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo,
1083  double snr)
1084 {
1085  Mac48Address sender = mpdu->GetHeader ().GetAddr1 ();
1086  NS_LOG_DEBUG ("Received ACK from=" << sender);
1087 
1088  NotifyReceivedNormalAck (mpdu);
1089 
1090  // When fragmentation is used, only update manager when the last fragment is acknowledged
1091  if (!mpdu->GetHeader ().IsMoreFragments ())
1092  {
1093  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxInfo, ackTxVector);
1094  m_mac->GetWifiRemoteStationManager ()->ReportDataOk (mpdu, rxInfo.snr, ackTxVector.GetMode (),
1095  snr, txVector);
1096  }
1097  // cancel the timer
1098  m_txTimer.Cancel ();
1099  m_channelAccessManager->NotifyAckTimeoutResetNow ();
1100 
1101  // The CW shall be reset to aCWmin after every successful attempt to transmit
1102  // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1103  m_dcf->ResetCw ();
1104 
1105  if (mpdu->GetHeader ().IsMoreFragments ())
1106  {
1107  // enqueue the next fragment
1109  m_dcf->GetWifiMacQueue ()->PushFront (next);
1110  m_moreFragments = true;
1111  }
1112 
1114 }
1115 
1116 void
1118 {
1119  NS_LOG_FUNCTION (this << *mpdu);
1120 
1121  // inform the MAC that the transmission was successful
1122  if (!m_ackedMpduCallback.IsNull ())
1123  {
1124  m_ackedMpduCallback (mpdu);
1125  }
1126 }
1127 
1128 void
1130  const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus)
1131 {
1132  NS_ASSERT_MSG (false, "A non-QoS station should not receive an A-MPDU");
1133 }
1134 
1135 } //namespace ns3
void SetAckedMpduCallback(AckedMpdu callback)
Set the callback to invoke when an MPDU is successfully acked.
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:83
bool IsRetry(void) const
Return if the Retry bit is set.
void SetRetry(void)
Set the Retry bit in the Frame Control field.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
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:429
void SetMoreFragments(void)
Set the More Fragment bit in the Frame Control field.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
bool m_moreFragments
true if a fragment has to be sent after a SIFS
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
microsecond
Definition: nstime.h:117
#define PSDU_DURATION_SAFEGUARD
virtual void DequeueMpdu(Ptr< WifiMacQueueItem > mpdu)
Dequeue the given MPDU from the queue in which it is stored.
void SendCtsToSelf(const WifiTxParameters &txParams)
Send CTS for a CTS-to-self mechanism.
WifiTxTimer m_txTimer
the timer set upon frame transmission
virtual void SetProtectionManager(Ptr< WifiProtectionManager > protectionManager)
Set the Protection Manager to use.
AckedMpdu m_ackedMpduCallback
the acknowledged MPDU callback
bool IsPromisc(void) const
Check if the device is operating in promiscuous mode.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SendMpduWithProtection(Ptr< WifiMacQueueItem > mpdu, WifiTxParameters &txParams)
Send an MPDU with the given TX parameters (with the specified protection).
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
virtual void SetAddress(Mac48Address address)
Set the MAC address.
Ptr< WifiProtectionManager > GetProtectionManager(void) const
Get the Protection Manager used by this node.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Ptr< WifiPhy > m_phy
the PHY layer on this station
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:274
bool IsCtl(void) const
Return true if the Type is Control.
#define min(a, b)
Definition: 80211b.c:42
Ptr< Packet > m_fragmentedPacket
the MSDU being fragmented
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1124
std::unique_ptr< WifiProtection > m_protection
protection method
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:209
void SetPromisc(void)
Enable promiscuous mode.
uint32_t GetSize(void) const
Return the size of the packet stored by this item, including header size and trailer size...
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
void Clear(void)
Reset the TX parameters.
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
Time acknowledgmentTime
time required by the acknowledgment method
WifiAcknowledgment is an abstract base struct.
Ptr< WifiMacQueueItem > m_mpdu
the MPDU being transmitted
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
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
#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
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...
Time GetTimeStamp(void) const
Get the timestamp included in this item.
Information needed to remove an MSDU from the queue.
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octects of the IEEE 802.11 MAC FCS field.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
ConstIterator it
iterator pointing to the MSDU in the queue
virtual void ForwardMpduDown(Ptr< WifiMacQueueItem > mpdu, WifiTxVector &txVector)
Forward an MPDU down to the PHY layer.
WifiTxVector ackTxVector
Ack TXVECTOR.
WifiTxVector ctsTxVector
CTS TXVECTOR.
virtual void CalculateProtectionTime(WifiProtection *protection) const
Calculate the time required to protect a frame according to the given protection method.
bool m_promisc
Flag if the device is operating in promiscuous mode.
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:333
uint32_t GetAckSize(void)
Return the total Ack size (including FCS trailer).
Definition: wifi-utils.cc:164
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Time m_txDuration
TX duration of the frame.
ns3::Time timeout
const char * GetTypeString(void) const
Return a string corresponds to the header type.
void NotifySwitchingStartNow(Time duration)
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1682
virtual void TransmissionFailed(void)
Take necessary actions upon a transmission failure.
WifiTxVector rtsTxVector
RTS TXVECTOR.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:47
const Method method
acknowledgment method
virtual void CalculateAcknowledgmentTime(WifiAcknowledgment *acknowledgment) const
Calculate the time required to acknowledge a frame according to the given acknowledgment method...
virtual void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
virtual void CtsTimeout(Ptr< WifiMacQueueItem > rts, const WifiTxVector &txVector)
Called when the CTS timeout expires.
Ptr< WifiAckManager > GetAckManager(void) const
Get the Acknowledgment Manager used by this node.
double Get(void) const
Return the SNR value.
Definition: snr-tag.cc:89
Ptr< RegularWifiMac > m_mac
the MAC layer on this station
DroppedMpdu m_droppedMpduCallback
the dropped MPDU callback
virtual void SetMacRxMiddle(const Ptr< MacRxMiddle > rxMiddle)
Set the MAC RX Middle to use.
phy
Definition: third.py:93
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...
Ptr< WifiMacQueueItem > GetFirstFragmentIfNeeded(Ptr< WifiMacQueueItem > mpdu)
Fragment the given MPDU if needed.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1610
const PsduInfoMap & GetPsduInfoMap(void) const
Get a const reference to the map containing information about PSDUs.
void UpdateFailedCw(void)
Update the value of the CW variable to take into account a transmission failure.
Definition: txop.cc:195
virtual void SetAckManager(Ptr< WifiAckManager > ackManager)
Set the Acknowledgment Manager to use.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:66
Mac48Address m_bssid
BSSID address (Mac48Address)
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
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...
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
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 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.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
bool IsBeacon(void) const
Return true if the header is a Beacon header.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1313
Reason GetReason(void) const
Get the reason why the timer was started.
virtual void UpdateNav(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Update the NAV, if needed, based on the Duration/ID of the given psdu.
virtual void SetMacTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set the MAC TX Middle to use.
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
EventId m_navResetEvent
the event to reset the NAV after an RTS
mac
Definition: third.py:99
virtual void SetChannelAccessManager(const Ptr< ChannelAccessManager > channelAccessManager)
Set the channel access manager to use.
virtual void NotifyChannelReleased(void)
Called by the FrameExchangeManager to notify the completion of the transmissions. ...
Definition: txop.cc:349
bool IsCts(void) const
Return true if the header is a CTS header.
virtual bool StartTransmission(Ptr< Txop > dcf)
Request the FrameExchangeManager to start a frame exchange sequence.
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:319
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 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...
Time GetDuration(void) const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition: wifi-psdu.cc:141
Ptr< WifiAckManager > m_ackManager
Acknowledgment manager.
Time protectionTime
time required by the protection method
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
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...
Mac48Address m_self
the MAC address of this device
WifiProtection is an abstract base struct.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
Ptr< const Packet > GetPacket(void) const
Get the packet stored in this item.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
bool IsFragment(void) const
Return true if this item contains an MSDU fragment, false otherwise.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SendRts(const WifiTxParameters &txParams)
Send RTS to begin RTS-CTS-Data-Ack transaction.
bool IsData(void) const
Return true if the Type is DATA.
This class is used to handle the timer that a station starts when transmitting a frame that solicits ...
Definition: wifi-tx-timer.h:47
address
Definition: first.py:44
Ptr< WifiMacQueueItem > Dequeue(void) override
Dequeue the packet in the front of the queue.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
void DoDispose() override
Destructor implementation.
void Cancel(void)
Cancel the timer.
an EUI-48 address
Definition: mac48-address.h:43
bool IsRunning(void) const
Return true if the timer is running.
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.
WifiRtsCtsProtection specifies that RTS/CTS protection method is used.
void SendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiMode rtsTxMode, double rtsSnr)
Send CTS after receiving RTS.
bool IsGroup(void) const
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual void SetWifiMac(const Ptr< RegularWifiMac > mac)
Set the MAC layer to use.
WifiTxParameters m_txParams
the TX parameters for the current frame
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.
static TypeId GetTypeId(void)
Get the type ID.
void SendNormalAck(const WifiMacHeader &hdr, const WifiTxVector &dataTxVector, double dataSnr)
Send Normal Ack.
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...
void AddMpdu(Ptr< const WifiMacQueueItem > mpdu)
Record that an MPDU is being added to the current frame.
bool IsMoreFragments(void) const
Return if the More Fragment bit is set.
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:342
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
uint32_t GetCtsSize(void)
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:217
#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
uint16_t GetRawDuration(void) const
Return the raw duration from the Duration/ID field.
const WifiTxTimer & GetWifiTxTimer(void) const
Get a const reference to the WifiTxTimer object.
Ptr< WifiProtectionManager > m_protectionManager
Protection manager.
void Reschedule(const Time &delay)
Reschedule the timer to time out the given amount of time from the moment this function is called...
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:635
WifiMacQueue * queue
pointer to the queue where the MSDU is enqueued
bool IsMgt(void) const
Return true if the Type is Management.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
void NormalAckTimeout(Ptr< WifiMacQueueItem > mpdu, const WifiTxVector &txVector)
Called when the Ack timeout expires.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:910
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
virtual void Reset(void)
Reset this frame exchange manager.
bool IsQueued(void) const
Return true if this item is stored in some queue, false otherwise.
bool IsProbeResp(void) const
Return true if the header is a Probe Response header.
double snr
SNR in linear scale.
Definition: phy-entity.h:68
bool PushFront(Ptr< WifiMacQueueItem > item)
Enqueue the given Wifi MAC queue item at the front of the queue.
virtual void SetBssid(Mac48Address bssid)
Set the Basic Service Set Identification.
bool IsStrictlyNegative(void) const
Exactly equivalent to t < 0.
Definition: nstime.h:325
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
WifiTxVector ctsTxVector
CTS TXVECTOR.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:150
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism...
Ptr< Txop > m_dcf
the DCF/EDCAF that gained channel access
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
Time GetSlot(void) const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:922
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:325
WifiCtsToSelfProtection specifies that CTS-to-self protection method is used.
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1604
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:1768
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...
const Method method
protection method
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
bool IsRts(void) const
Return true if the header is a RTS header.
Time m_navEnd
NAV expiration time.
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)
virtual void RetransmitMpduAfterMissedAck(Ptr< WifiMacQueueItem > mpdu) const
Retransmit an MPDU that was not acknowledged.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data...
virtual void TransmissionSucceeded(void)
Take necessary actions upon a transmission success.
bool IsAck(void) const
Return true if the header is an Ack header.
void RxStartIndication(WifiTxVector txVector, Time psduDuration)
void DoSendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiTxVector &ctsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Ptr< WifiMacQueueItem > GetNextFragment(void)
Get the next fragment of the current MSDU.
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
virtual void NotifyReceivedNormalAck(Ptr< WifiMacQueueItem > mpdu)
Notify other components that an MPDU was acknowledged.
A base class which provides memory management and object aggregation.
Definition: object.h:87
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Set the callback to invoke when an MPDU is dropped.
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...
Mac48Address GetAddr1(void) const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:111
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:978
uint32_t GetPacketSize(void) const
Return the size in bytes of the packet or control header or management header stored by this item...
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
WifiNormalAck specifies that acknowledgment via Normal Ack is required.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
uint8_t GetFragmentNumber(void) const
Return the fragment number of the header.
virtual void SetWifiPhy(const Ptr< WifiPhy > phy)
Set the PHY layer to use.
void SetFragmentNumber(uint8_t frag)
Set the fragment number of the header.
Ptr< MacTxMiddle > m_txMiddle
the MAC TX Middle on this station
void ResetCw(void)
Update the value of the CW variable to take into account a transmission success or a transmission abo...
Definition: txop.cc:187
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
const std::list< QueueIteratorPair > & GetQueueIteratorPairs(void) const
Get a const reference to the list of iterators pointing to the positions of the items in the queue...
void SendMpdu(void)
Send the current MPDU, which can be acknowledged by a Normal 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:1642
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
Implements the IEEE 802.11 MAC header.
virtual void NavResetTimeout(void)
Reset the NAV upon expiration of the NAV reset timer.
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
virtual void RetransmitMpduAfterMissedCts(Ptr< WifiMacQueueItem > mpdu) const
Retransmit an MPDU that was not sent because a CTS was not received.