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 "channel-access-manager.h"
25 #include "wifi-utils.h"
26 #include "snr-tag.h"
27 #include "wifi-mac-queue.h"
30 #include "wifi-mac-trailer.h"
31 
32 #undef NS_LOG_APPEND_CONTEXT
33 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
34 
35 // Time (in nanoseconds) to be added to the PSDU duration to yield the duration
36 // of the timer that is started when the PHY indicates the start of the reception
37 // of a frame and we are waiting for a response.
38 #define PSDU_DURATION_SAFEGUARD 400
39 
40 namespace ns3 {
41 
42 NS_LOG_COMPONENT_DEFINE ("FrameExchangeManager");
43 
44 NS_OBJECT_ENSURE_REGISTERED (FrameExchangeManager);
45 
46 TypeId
48 {
49  static TypeId tid = TypeId ("ns3::FrameExchangeManager")
50  .SetParent<Object> ()
51  .AddConstructor<FrameExchangeManager> ()
52  .SetGroupName ("Wifi")
53  ;
54  return tid;
55 }
56 
58  : m_navEnd (Seconds (0)),
59  m_promisc (false),
60  m_moreFragments (false)
61 {
62  NS_LOG_FUNCTION (this);
63 }
64 
66 {
68 }
69 
70 void
72 {
73  NS_LOG_FUNCTION (this);
74  m_txTimer.Cancel ();
76  {
78  }
80  m_mpdu = 0;
81  m_txParams.Clear ();
82  m_dcf = 0;
83 }
84 
85 void
87 {
88  NS_LOG_FUNCTION (this);
89  Reset ();
91  m_mac = 0;
92  m_txMiddle = 0;
93  m_rxMiddle = 0;
96  m_ackManager = 0;
97  if (m_phy != 0)
98  {
99  m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
101  }
102  m_phy = 0;
104 }
105 
106 void
108 {
109  NS_LOG_FUNCTION (this << protectionManager);
110  m_protectionManager = protectionManager;
111 }
112 
115 {
116  return m_protectionManager;
117 }
118 
119 void
121 {
122  NS_LOG_FUNCTION (this << ackManager);
123  m_ackManager = ackManager;
124 }
125 
128 {
129  return m_ackManager;
130 }
131 
132 void
134 {
135  NS_LOG_FUNCTION (this << mac);
136  m_mac = mac;
137 }
138 
139 void
141 {
142  NS_LOG_FUNCTION (this << txMiddle);
143  m_txMiddle = txMiddle;
144 }
145 
146 void
148 {
149  NS_LOG_FUNCTION (this << rxMiddle);
150  m_rxMiddle = rxMiddle;
151 }
152 
153 void
155 {
156  NS_LOG_FUNCTION (this << channelAccessManager);
157  m_channelAccessManager = channelAccessManager;
158 }
159 
160 void
162 {
163  NS_LOG_FUNCTION (this << phy);
164  m_phy = phy;
165  m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin",
168 }
169 
170 void
172 {
173  m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
176  m_phy = 0;
177 }
178 
179 void
181 {
182  NS_LOG_FUNCTION (this << address);
183  m_self = address;
184 }
185 
186 void
188 {
189  NS_LOG_FUNCTION (this << bssid);
190  m_bssid = bssid;
191 }
192 
193 void
195 {
196  NS_LOG_FUNCTION (this << &callback);
197  m_droppedMpduCallback = callback;
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION (this << &callback);
204  m_ackedMpduCallback = callback;
205 }
206 
207 void
209 {
210  m_promisc = true;
211 }
212 
213 bool
215 {
216  return m_promisc;
217 }
218 
219 const WifiTxTimer&
221 {
222  return m_txTimer;
223 }
224 
225 void
227 {
229  {
231  }
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION (this << "PSDU reception started for " << psduDuration.As (Time::US)
238  << " (txVector: " << txVector << ")");
239 
240  if (psduDuration.IsZero ())
241  {
242  // PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered),
243  // no need to reschedule timeouts (CCA will take over)
244  return;
245  }
246 
247  NS_ASSERT (psduDuration.IsStrictlyPositive ());
249  "The TX timer and the NAV reset event cannot be both running");
250 
251  if (m_txTimer.IsRunning ())
252  {
253  // we are waiting for a response and something arrived
254  NS_LOG_DEBUG ("Rescheduling timeout event");
256  // PHY has switched to RX, so we can reset the ack timeout
257  m_channelAccessManager->NotifyAckTimeoutResetNow ();
258  }
259  else if (m_navResetEvent.IsRunning ())
260  {
262  }
263 }
264 
265 bool
267 {
268  NS_LOG_FUNCTION (this << dcf);
269 
270  NS_ASSERT (m_mpdu == 0);
271  if (m_txTimer.IsRunning ())
272  {
273  m_txTimer.Cancel ();
274  }
275  m_dcf = dcf;
276 
277  Ptr<WifiMacQueue> queue = dcf->GetWifiMacQueue ();
278 
279  // Even though channel access is requested when the queue is not empty, at
280  // the time channel access is granted the lifetime of the packet might be
281  // expired and the queue might be empty.
282  if (queue->IsEmpty ())
283  {
284  NS_LOG_DEBUG ("Queue empty");
286  m_dcf = 0;
287  return false;
288  }
289 
291  Ptr<WifiMacQueueItem> mpdu = *queue->Peek ()->GetQueueIteratorPairs ().front ().it;
292  NS_ASSERT (mpdu != 0);
293  NS_ASSERT (mpdu->GetHeader ().IsData () || mpdu->GetHeader ().IsMgt ());
294 
295  // assign a sequence number if this is not a fragment nor a retransmission
296  if (!mpdu->IsFragment () && !mpdu->GetHeader ().IsRetry ())
297  {
298  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&mpdu->GetHeader ());
299  mpdu->GetHeader ().SetSequenceNumber (sequence);
300  }
301 
302  NS_LOG_DEBUG ("MPDU payload size=" << mpdu->GetPacketSize () <<
303  ", to=" << mpdu->GetHeader ().GetAddr1 () <<
304  ", seq=" << mpdu->GetHeader ().GetSequenceControl ());
305 
306  // check if the MSDU needs to be fragmented
307  mpdu = GetFirstFragmentIfNeeded (mpdu);
308 
310  NS_ASSERT (m_ackManager != 0);
311  WifiTxParameters txParams;
312  txParams.m_txVector = m_mac->GetWifiRemoteStationManager ()->GetDataTxVector (mpdu->GetHeader ());
313  txParams.m_protection = m_protectionManager->TryAddMpdu (mpdu, txParams);
314  txParams.m_acknowledgment = m_ackManager->TryAddMpdu (mpdu, txParams);
315  txParams.AddMpdu (mpdu);
316  UpdateTxDuration (mpdu->GetHeader ().GetAddr1 (), txParams);
317 
318  SendMpduWithProtection (mpdu, txParams);
319 
320  return true;
321 }
322 
325 {
326  NS_LOG_FUNCTION (this << *mpdu);
327 
328  if (mpdu->IsFragment ())
329  {
330  // a fragment cannot be further fragmented
332  }
333  else if (m_mac->GetWifiRemoteStationManager ()->NeedFragmentation (mpdu))
334  {
335  NS_LOG_DEBUG ("Fragmenting the MSDU");
336  m_fragmentedPacket = mpdu->GetPacket ()->Copy ();
337  // dequeue the MSDU
339  queueIt.queue->Dequeue (queueIt.it);
340  // create the first fragment
341  mpdu->GetHeader ().SetMoreFragments ();
342  Ptr<Packet> fragment = m_fragmentedPacket->CreateFragment (0, m_mac->GetWifiRemoteStationManager ()->GetFragmentSize (mpdu, 0));
343  // enqueue the first fragment
344  Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (fragment, mpdu->GetHeader (), mpdu->GetTimeStamp ());
345  queueIt.queue->PushFront (item);
346  return item;
347  }
348  return mpdu;
349 }
350 
351 void
353 {
354  NS_LOG_FUNCTION (this << *mpdu << &txParams);
355 
356  m_mpdu = mpdu;
357  m_txParams = std::move (txParams);
358 
359  // If protection is required, the MPDU must be stored in some queue because
360  // it is not put back in a queue if the RTS/CTS exchange fails
362  || m_mpdu->GetHeader ().IsCtl ()
363  || m_mpdu->IsQueued ());
364 
365  // Make sure that the acknowledgment time has been computed, so that SendRts()
366  // and SendCtsToSelf() can reuse this value.
368 
369  if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min ())
370  {
372  }
373 
374  // Set QoS Ack policy if this is a QoS data frame
376 
377  switch (m_txParams.m_protection->method)
378  {
381  break;
384  break;
386  SendMpdu ();
387  break;
388  default:
389  NS_ABORT_MSG ("Unknown protection type");
390  }
391 }
392 
393 void
395 {
396  NS_LOG_FUNCTION (this);
397 
399 
401 
403  {
405  }
407  {
410 
411  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
412  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
413  // aRxPHYStartDelay equals the time to transmit the PHY header.
414  WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (m_txParams.m_acknowledgment.get ());
415 
416  Time timeout = txDuration
417  + m_phy->GetSifs ()
418  + m_phy->GetSlot ()
419  + m_phy->CalculatePhyPreambleAndHeaderDuration (normalAcknowledgment->ackTxVector);
422  this, m_mpdu, m_txParams.m_txVector);
423  m_channelAccessManager->NotifyAckTimeoutStartNow (timeout);
424  }
425  else
426  {
427  NS_ABORT_MSG ("Unable to handle the selected acknowledgment method ("
428  << m_txParams.m_acknowledgment.get () << ")");
429  }
430 
431  // transmit the MPDU
433 
435  {
436  // we are done with frames that do not require acknowledgment
437  m_mpdu = 0;
438  }
439 }
440 
441 void
443 {
444  NS_LOG_FUNCTION (this << *mpdu << txVector);
445 
446  // The MPDU is about to be transmitted, we can now dequeue it if it is stored in a queue
447  DequeueMpdu (mpdu);
448 
449  m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
450 }
451 
452 void
454 {
455  NS_LOG_DEBUG (this << *mpdu);
456 
457  if (mpdu->IsQueued ())
458  {
460  NS_ASSERT (*queueIt.it == mpdu);
461  queueIt.queue->Dequeue (queueIt.it);
462  }
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);
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  m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
786  m_dcf->ResetCw ();
787  }
788  else
789  {
790  NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
791  mpdu->GetHeader ().SetRetry ();
793  m_dcf->UpdateFailedCw ();
794  }
795 
796  m_mpdu = 0;
798 }
799 
800 void
802 {
803  NS_LOG_FUNCTION (this << *mpdu);
804 
805  // insert the MPDU in the DCF queue again
806  m_dcf->GetWifiMacQueue ()->PushFront (mpdu);
807 }
808 
809 void
811 {
812  NS_LOG_FUNCTION (this << *rts << txVector);
813 
814  m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_mpdu->GetHeader ());
815 
816  if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (m_mpdu))
817  {
818  NS_LOG_DEBUG ("Missed CTS, discard MPDU");
819  // Dequeue the MPDU if it is stored in a queue
822  m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (m_mpdu->GetHeader ());
823  m_dcf->ResetCw ();
824  }
825  else
826  {
827  NS_LOG_DEBUG ("Missed CTS, retransmit RTS");
829  m_dcf->UpdateFailedCw ();
830  }
831  m_mpdu = 0;
833 }
834 
835 void
837 {
838  NS_LOG_FUNCTION (this << *mpdu);
839 
840  // the MPDU should be still in the DCF queue, unless it expired.
841  // If the MPDU has never been transmitted, it will be assigned a sequence
842  // number again the next time we try to transmit it. Therefore, we need to
843  // make its sequence number available again
844  if (!mpdu->GetHeader ().IsRetry ())
845  {
846  m_txMiddle->SetSequenceNumberFor (&mpdu->GetHeader ());
847  }
848 }
849 
850 void
852 {
853  NS_LOG_DEBUG ("Switching channel. Cancelling MAC pending events");
854  m_mac->GetWifiRemoteStationManager ()->Reset ();
855  Reset ();
856 }
857 
858 void
860 {
861  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
862  Reset ();
863 }
864 
865 void
867 {
868  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
869  Reset ();
870 }
871 
872 void
874  WifiTxVector txVector, std::vector<bool> perMpduStatus)
875 {
876  NS_LOG_FUNCTION (this << psdu << rxSignalInfo << txVector << perMpduStatus.size ()
877  << std::all_of (perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
878 
879  if (!perMpduStatus.empty ())
880  {
881  // for A-MPDUs, we get here only once
882  PreProcessFrame (psdu, txVector);
883  }
884 
885  // ignore unicast frames that are not addressed to us
886  Mac48Address addr1 = psdu->GetAddr1 ();
887  if (!addr1.IsGroup () && addr1 != m_self)
888  {
889  if (m_promisc && psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsData ())
890  {
891  m_rxMiddle->Receive (*psdu->begin ());
892  }
893  return;
894  }
895 
896  if (psdu->GetNMpdus () == 1)
897  {
898  // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
899  // then it must contain a single value which must be true (i.e., the MPDU
900  // has been correctly received)
901  NS_ASSERT (perMpduStatus.empty () || (perMpduStatus.size () == 1 && perMpduStatus[0]));
902  // Ack and CTS do not carry Addr2
903  if (!psdu->GetHeader (0).IsAck () && !psdu->GetHeader (0).IsCts ())
904  {
905  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (psdu->GetHeader (0).GetAddr2 (),
906  rxSignalInfo, txVector);
907  }
908  ReceiveMpdu (*(psdu->begin ()), rxSignalInfo, txVector, perMpduStatus.empty ());
909  }
910  else
911  {
912  EndReceiveAmpdu (psdu, rxSignalInfo, txVector, perMpduStatus);
913  }
914 }
915 
916 void
918 {
919  NS_LOG_FUNCTION (this << psdu << txVector);
920 
921  UpdateNav (psdu, txVector);
922 }
923 
924 void
926 {
927  NS_LOG_FUNCTION (this << psdu << txVector);
928 
929  if (psdu->GetHeader (0).GetRawDuration () > 32767)
930  {
931  // When the contents of a received Duration/ID field, treated as an unsigned
932  // integer, are greater than 32 768, the contents are interpreted as appropriate
933  // for the frame type and subtype or ignored if the receiving MAC entity does
934  // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
935  // sec. 10.27.3)
936  return;
937  }
938 
939  Time duration = psdu->GetDuration ();
940  NS_LOG_DEBUG ("Duration/ID=" << duration);
941 
942  if (psdu->GetAddr1 () == m_self)
943  {
944  // When the received frame’s RA is equal to the STA’s own MAC address, the STA
945  // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
946  return;
947  }
948 
949  // For all other received frames the STA shall update its NAV when the received
950  // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
951  Time navEnd = Simulator::Now () + duration;
952  if (navEnd > m_navEnd)
953  {
954  m_navEnd = navEnd;
955  NS_LOG_DEBUG ("Updated NAV=" << m_navEnd);
956 
957  // A STA that used information from an RTS frame as the most recent basis to update
958  // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
959  // primitive is received from the PHY during a NAVTimeout period starting when the
960  // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
961  // the RTS frame. NAVTimeout period is equal to:
962  // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
963  // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
964  // rate at which the RTS frame used for the most recent NAV update was received
965  // (IEEE 802.11-2016 sec. 10.3.2.4)
966  if (psdu->GetHeader (0).IsRts ())
967  {
968  Time navResetDelay = 2 * m_phy->GetSifs ()
970  m_phy->GetPhyBand ())
972  + 2 * m_phy->GetSlot ();
974  }
975  }
976 
977  m_channelAccessManager->NotifyNavStartNow (duration);
978 }
979 
980 void
982 {
984  m_channelAccessManager->NotifyNavResetNow (Seconds (0));
985 }
986 
987 void
989  const WifiTxVector& txVector, bool inAmpdu)
990 {
991  NS_LOG_FUNCTION (this << *mpdu << rxSignalInfo << txVector << inAmpdu);
992  // The received MPDU is either broadcast or addressed to this station
993  NS_ASSERT (mpdu->GetHeader ().GetAddr1 ().IsGroup ()
994  || mpdu->GetHeader ().GetAddr1 () == m_self);
995 
996  double rxSnr = rxSignalInfo.snr;
997  const WifiMacHeader& hdr = mpdu->GetHeader ();
998 
999  if (hdr.IsCtl ())
1000  {
1001  if (hdr.IsRts ())
1002  {
1003  NS_ABORT_MSG_IF (inAmpdu, "Received RTS as part of an A-MPDU");
1004 
1005  // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1006  // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1007  // - Otherwise, the STA shall not respond with a CTS frame
1008  // (IEEE 802.11-2016 sec. 10.3.2.7)
1009  if (m_navEnd <= Simulator::Now ())
1010  {
1011  NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
1013  this, hdr, txVector.GetMode (), rxSnr);
1014  }
1015  else
1016  {
1017  NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
1018  }
1019  }
1020  else if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS
1021  && m_mpdu != 0)
1022  {
1023  NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU");
1024  NS_ASSERT (hdr.GetAddr1 () == m_self);
1025 
1026  Mac48Address sender = m_mpdu->GetHeader ().GetAddr1 ();
1027  NS_LOG_DEBUG ("Received CTS from=" << sender);
1028 
1029  SnrTag tag;
1030  mpdu->GetPacket ()->PeekPacketTag (tag);
1031  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector);
1032  m_mac->GetWifiRemoteStationManager ()->ReportRtsOk (m_mpdu->GetHeader (),
1033  rxSnr, txVector.GetMode (), tag.Get ());
1034 
1035  m_txTimer.Cancel ();
1036  m_channelAccessManager->NotifyCtsTimeoutResetNow ();
1038  }
1039  else if (hdr.IsAck () && m_mpdu != 0 && m_txTimer.IsRunning ()
1041  {
1042  NS_ASSERT (hdr.GetAddr1 () == m_self);
1043  SnrTag tag;
1044  mpdu->GetPacket ()->PeekPacketTag (tag);
1045  ReceivedNormalAck (m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ());
1046  m_mpdu = 0;
1047  }
1048  }
1049  else if (hdr.IsMgt ())
1050  {
1051  NS_ABORT_MSG_IF (inAmpdu, "Received management frame as part of an A-MPDU");
1052 
1053  if (hdr.IsBeacon () || hdr.IsProbeResp ())
1054  {
1055  // Apply SNR tag for beacon quality measurements
1056  SnrTag tag;
1057  tag.Set (rxSnr);
1058  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
1059  packet->AddPacketTag (tag);
1060  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1061  }
1062 
1063  if (hdr.GetAddr1 () == m_self)
1064  {
1065  NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1067  this, hdr, txVector, rxSnr);
1068  }
1069 
1070  m_rxMiddle->Receive (mpdu);
1071  }
1072  else if (hdr.IsData () && !hdr.IsQosData ())
1073  {
1074  if (hdr.GetAddr1 () == m_self)
1075  {
1076  NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1078  this, hdr, txVector, rxSnr);
1079  }
1080 
1081  m_rxMiddle->Receive (mpdu);
1082  }
1083 }
1084 
1085 void
1087  const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo,
1088  double snr)
1089 {
1090  Mac48Address sender = mpdu->GetHeader ().GetAddr1 ();
1091  NS_LOG_DEBUG ("Received ACK from=" << sender);
1092 
1093  NotifyReceivedNormalAck (mpdu);
1094 
1095  // When fragmentation is used, only update manager when the last fragment is acknowledged
1096  if (!mpdu->GetHeader ().IsMoreFragments ())
1097  {
1098  m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxInfo, ackTxVector);
1099  m_mac->GetWifiRemoteStationManager ()->ReportDataOk (mpdu, rxInfo.snr, ackTxVector.GetMode (),
1100  snr, txVector);
1101  }
1102  // cancel the timer
1103  m_txTimer.Cancel ();
1104  m_channelAccessManager->NotifyAckTimeoutResetNow ();
1105 
1106  // The CW shall be reset to aCWmin after every successful attempt to transmit
1107  // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1108  m_dcf->ResetCw ();
1109 
1110  if (mpdu->GetHeader ().IsMoreFragments ())
1111  {
1112  // enqueue the next fragment
1114  m_dcf->GetWifiMacQueue ()->PushFront (next);
1115  m_moreFragments = true;
1116  }
1117 
1119 }
1120 
1121 void
1123 {
1124  NS_LOG_FUNCTION (this << *mpdu);
1125 
1126  // inform the MAC that the transmission was successful
1127  if (!m_ackedMpduCallback.IsNull ())
1128  {
1129  m_ackedMpduCallback (mpdu);
1130  }
1131 }
1132 
1133 void
1135  const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus)
1136 {
1137  NS_ASSERT_MSG (false, "A non-QoS station should not receive an A-MPDU");
1138 }
1139 
1140 } //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 DoDispose()
Destructor implementation.
Ptr< WifiMacQueueItem > Dequeue(void)
Dequeue the packet in the front of the queue.
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:1616
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.
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:301
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
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 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:1774
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.