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 ()->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 
341 void
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 
383 void
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 ()
418  + m_phy->CalculatePhyPreambleAndHeaderDuration (normalAcknowledgment->ackTxVector);
421  this, m_mpdu, m_txParams.m_txVector);
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 
440 void
442 {
443  NS_LOG_FUNCTION (this << *mpdu << txVector);
444 
445  m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
446 }
447 
448 void
450 {
451  NS_LOG_DEBUG (this << *mpdu);
452 
453  if (mpdu->IsQueued ())
454  {
455  m_mac->GetTxopQueue (mpdu->GetQueueAc ())->DequeueIfQueued (mpdu);
456  }
457 }
458 
459 uint32_t
461 {
462  return mpdu->GetSize ();
463 }
464 
465 void
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 
494 void
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 
514 Time
515 FrameExchangeManager::GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
516  const WifiTxParameters& txParams) const
517 {
518  return m_phy->CalculateTxDuration (ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand ());
519 }
520 
521 void
523 {
524  txParams.m_txDuration = GetTxDuration (txParams.GetSize (receiver), receiver, txParams);
525 }
526 
527 Time
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 
555 Time
556 FrameExchangeManager::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 
568 void
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 
608 void
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 
640 void
641 FrameExchangeManager::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 
649 Time
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 
658 void
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 
685 void
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 
745 void
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 
765 void
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 
774 void
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");
784  NotifyPacketDiscarded (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 ();
795  m_dcf->UpdateFailedCw ();
796  }
797 
798  m_mpdu = 0;
800 }
801 
802 void
804 {
805  NS_LOG_FUNCTION (this << *mpdu);
806 }
807 
808 void
810 {
811  NS_LOG_FUNCTION (this << *rts << txVector);
812 
813  DoCtsTimeout (Create<WifiPsdu> (m_mpdu, true));
814  m_mpdu = nullptr;
815 }
816 
817 void
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);
832  NotifyPacketDiscarded (mpdu);
833  }
834  m_dcf->ResetCw ();
835  }
836  else
837  {
838  NS_LOG_DEBUG ("Missed CTS, retransmit MPDU(s)");
839  m_dcf->UpdateFailedCw ();
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  {
847  ReleaseSequenceNumber (mpdu);
848  }
850 }
851 
852 void
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 
867 void
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);
897  NotifyPacketDiscarded (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 
910 void
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 
925 void
927 {
928  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
929  Reset ();
930 }
931 
932 void
934 {
935  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
936  Reset ();
937 }
938 
939 void
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 
983 void
985 {
986  NS_LOG_FUNCTION (this << psdu << txVector);
987 
988  UpdateNav (psdu, txVector);
989 }
990 
991 void
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 ()
1036  + WifiPhy::CalculateTxDuration (GetCtsSize (), txVector,
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 
1048 void
1050 {
1051  NS_LOG_FUNCTION (this);
1052  m_navEnd = Simulator::Now ();
1053  m_channelAccessManager->NotifyNavResetNow (Seconds (0));
1054 }
1055 
1056 void
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 
1154 void
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 
1162  NotifyReceivedNormalAck (mpdu);
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 
1194 void
1196 {
1197  NS_LOG_FUNCTION (this << *mpdu);
1198 
1199  // inform the MAC that the transmission was successful
1200  if (!m_ackedMpduCallback.IsNull ())
1201  {
1202  m_ackedMpduCallback (mpdu);
1203  }
1204 }
1205 
1206 void
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:418
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:1506
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:887
Time GetSlot(void) const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:688
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1327
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:676
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:390
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1321
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.
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
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition: wifi-mac.h:69
mac
Definition: third.py:99
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.