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
GetTypeId(void)44 FrameExchangeManager::GetTypeId (void)
45 {
46   static TypeId tid = TypeId ("ns3::FrameExchangeManager")
47     .SetParent<Object> ()
48     .AddConstructor<FrameExchangeManager> ()
49     .SetGroupName ("Wifi")
50   ;
51   return tid;
52 }
53 
FrameExchangeManager()54 FrameExchangeManager::FrameExchangeManager ()
55   : m_navEnd (Seconds (0)),
56     m_promisc (false),
57     m_moreFragments (false)
58 {
59   NS_LOG_FUNCTION (this);
60 }
61 
~FrameExchangeManager()62 FrameExchangeManager::~FrameExchangeManager ()
63 {
64   NS_LOG_FUNCTION_NOARGS ();
65 }
66 
67 void
Reset(void)68 FrameExchangeManager::Reset (void)
69 {
70   NS_LOG_FUNCTION (this);
71   m_txTimer.Cancel ();
72   if (m_navResetEvent.IsRunning ())
73     {
74       m_navResetEvent.Cancel ();
75     }
76   m_navEnd = Simulator::Now ();
77   m_mpdu = 0;
78   m_txParams.Clear ();
79   m_dcf = 0;
80 }
81 
82 void
DoDispose(void)83 FrameExchangeManager::DoDispose (void)
84 {
85   NS_LOG_FUNCTION (this);
86   Reset ();
87   m_fragmentedPacket = 0;
88   m_mac = 0;
89   m_txMiddle = 0;
90   m_rxMiddle = 0;
91   m_channelAccessManager = 0;
92   m_protectionManager = 0;
93   m_ackManager = 0;
94   if (m_phy != 0)
95     {
96       m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
97                                             MakeCallback (&FrameExchangeManager::RxStartIndication, this));
98     }
99   m_phy = 0;
100   Object::DoDispose ();
101 }
102 
103 void
SetProtectionManager(Ptr<WifiProtectionManager> protectionManager)104 FrameExchangeManager::SetProtectionManager (Ptr<WifiProtectionManager> protectionManager)
105 {
106   NS_LOG_FUNCTION (this << protectionManager);
107   m_protectionManager = protectionManager;
108 }
109 
110 Ptr<WifiProtectionManager>
GetProtectionManager(void) const111 FrameExchangeManager::GetProtectionManager (void) const
112 {
113   return m_protectionManager;
114 }
115 
116 void
SetAckManager(Ptr<WifiAckManager> ackManager)117 FrameExchangeManager::SetAckManager (Ptr<WifiAckManager> ackManager)
118 {
119   NS_LOG_FUNCTION (this << ackManager);
120   m_ackManager = ackManager;
121 }
122 
123 Ptr<WifiAckManager>
GetAckManager(void) const124 FrameExchangeManager::GetAckManager (void) const
125 {
126   return m_ackManager;
127 }
128 
129 void
SetWifiMac(Ptr<RegularWifiMac> mac)130 FrameExchangeManager::SetWifiMac (Ptr<RegularWifiMac> mac)
131 {
132   NS_LOG_FUNCTION (this << mac);
133   m_mac = mac;
134 }
135 
136 void
SetMacTxMiddle(const Ptr<MacTxMiddle> txMiddle)137 FrameExchangeManager::SetMacTxMiddle (const Ptr<MacTxMiddle> txMiddle)
138 {
139   NS_LOG_FUNCTION (this << txMiddle);
140   m_txMiddle = txMiddle;
141 }
142 
143 void
SetMacRxMiddle(const Ptr<MacRxMiddle> rxMiddle)144 FrameExchangeManager::SetMacRxMiddle (const Ptr<MacRxMiddle> rxMiddle)
145 {
146   NS_LOG_FUNCTION (this << rxMiddle);
147   m_rxMiddle = rxMiddle;
148 }
149 
150 void
SetChannelAccessManager(const Ptr<ChannelAccessManager> channelAccessManager)151 FrameExchangeManager::SetChannelAccessManager (const Ptr<ChannelAccessManager> channelAccessManager)
152 {
153   NS_LOG_FUNCTION (this << channelAccessManager);
154   m_channelAccessManager = channelAccessManager;
155 }
156 
157 void
SetWifiPhy(Ptr<WifiPhy> phy)158 FrameExchangeManager::SetWifiPhy (Ptr<WifiPhy> phy)
159 {
160   NS_LOG_FUNCTION (this << phy);
161   m_phy = phy;
162   m_phy->TraceConnectWithoutContext ("PhyRxPayloadBegin",
163                                      MakeCallback (&FrameExchangeManager::RxStartIndication, this));
164   m_phy->SetReceiveOkCallback (MakeCallback (&FrameExchangeManager::Receive, this));
165 }
166 
167 void
ResetPhy(void)168 FrameExchangeManager::ResetPhy (void)
169 {
170   m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin",
171                                         MakeCallback (&FrameExchangeManager::RxStartIndication, this));
172   m_phy->SetReceiveOkCallback (MakeNullCallback<void, Ptr<WifiPsdu>, RxSignalInfo, WifiTxVector, std::vector<bool>> ());
173   m_phy = 0;
174 }
175 
176 void
SetAddress(Mac48Address address)177 FrameExchangeManager::SetAddress (Mac48Address address)
178 {
179   NS_LOG_FUNCTION (this << address);
180   m_self = address;
181 }
182 
183 void
SetBssid(Mac48Address bssid)184 FrameExchangeManager::SetBssid (Mac48Address bssid)
185 {
186   NS_LOG_FUNCTION (this << bssid);
187   m_bssid = bssid;
188 }
189 
190 void
SetDroppedMpduCallback(DroppedMpdu callback)191 FrameExchangeManager::SetDroppedMpduCallback (DroppedMpdu callback)
192 {
193   NS_LOG_FUNCTION (this << &callback);
194   m_droppedMpduCallback = callback;
195 }
196 
197 void
SetAckedMpduCallback(AckedMpdu callback)198 FrameExchangeManager::SetAckedMpduCallback (AckedMpdu callback)
199 {
200   NS_LOG_FUNCTION (this << &callback);
201   m_ackedMpduCallback = callback;
202 }
203 
204 void
SetPromisc(void)205 FrameExchangeManager::SetPromisc (void)
206 {
207   m_promisc = true;
208 }
209 
210 bool
IsPromisc(void) const211 FrameExchangeManager::IsPromisc (void) const
212 {
213   return m_promisc;
214 }
215 
216 const WifiTxTimer&
GetWifiTxTimer(void) const217 FrameExchangeManager::GetWifiTxTimer (void) const
218 {
219   return m_txTimer;
220 }
221 
222 void
NotifyPacketDiscarded(Ptr<const WifiMacQueueItem> mpdu)223 FrameExchangeManager::NotifyPacketDiscarded (Ptr<const WifiMacQueueItem> mpdu)
224 {
225   if (!m_droppedMpduCallback.IsNull ())
226     {
227       m_droppedMpduCallback (WIFI_MAC_DROP_REACHED_RETRY_LIMIT, mpdu);
228     }
229 }
230 
231 void
RxStartIndication(WifiTxVector txVector,Time psduDuration)232 FrameExchangeManager::RxStartIndication (WifiTxVector txVector, Time psduDuration)
233 {
234   NS_LOG_FUNCTION (this << "PSDU reception started for " << psduDuration.As (Time::US)
235                    << " (txVector: " << txVector << ")");
236 
237   NS_ASSERT_MSG (!m_txTimer.IsRunning () || !m_navResetEvent.IsRunning (),
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");
247       m_txTimer.Reschedule (psduDuration + NanoSeconds (PSDU_DURATION_SAFEGUARD));
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     {
254       m_navResetEvent.Cancel ();
255     }
256 }
257 
258 bool
StartTransmission(Ptr<Txop> dcf)259 FrameExchangeManager::StartTransmission (Ptr<Txop> dcf)
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");
278       m_dcf->NotifyChannelReleased ();
279       m_dcf = 0;
280       return false;
281     }
282 
283   m_dcf->NotifyChannelAccessed ();
284   Ptr<WifiMacQueueItem> mpdu = *queue->Peek ()->GetQueueIterator ();
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 
302   NS_ASSERT (m_protectionManager != 0);
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 
316 Ptr<WifiMacQueueItem>
GetFirstFragmentIfNeeded(Ptr<WifiMacQueueItem> mpdu)317 FrameExchangeManager::GetFirstFragmentIfNeeded (Ptr<WifiMacQueueItem> mpdu)
318 {
319   NS_LOG_FUNCTION (this << *mpdu);
320 
321   if (mpdu->IsFragment ())
322     {
323       // a fragment cannot be further fragmented
324       NS_ASSERT (m_fragmentedPacket != 0);
325     }
326   else if (m_mac->GetWifiRemoteStationManager ()->NeedFragmentation (mpdu))
327     {
328       NS_LOG_DEBUG ("Fragmenting the MSDU");
329       m_fragmentedPacket = mpdu->GetPacket ()->Copy ();
330       AcIndex ac = mpdu->GetQueueAc ();
331       // dequeue the MSDU
332       DequeueMpdu (mpdu);
333       // create the first fragment
334       mpdu->GetHeader ().SetMoreFragments ();
335       Ptr<Packet> fragment = m_fragmentedPacket->CreateFragment (0, m_mac->GetWifiRemoteStationManager ()->GetFragmentSize (mpdu, 0));
336       // enqueue the first fragment
337       Ptr<WifiMacQueueItem> item = Create<WifiMacQueueItem> (fragment, mpdu->GetHeader (), mpdu->GetTimeStamp ());
338       m_mac->GetTxopQueue (ac)->PushFront (item);
339       return item;
340     }
341   return mpdu;
342 }
343 
344 void
SendMpduWithProtection(Ptr<WifiMacQueueItem> mpdu,WifiTxParameters & txParams)345 FrameExchangeManager::SendMpduWithProtection (Ptr<WifiMacQueueItem> mpdu, WifiTxParameters& txParams)
346 {
347   NS_LOG_FUNCTION (this << *mpdu << &txParams);
348 
349   m_mpdu = mpdu;
350   m_txParams = std::move (txParams);
351 
352   // If protection is required, the MPDU must be stored in some queue because
353   // it is not put back in a queue if the RTS/CTS exchange fails
354   NS_ASSERT (m_txParams.m_protection->method == WifiProtection::NONE
355              || m_mpdu->GetHeader ().IsCtl ()
356              || m_mpdu->IsQueued ());
357 
358   // Make sure that the acknowledgment time has been computed, so that SendRts()
359   // and SendCtsToSelf() can reuse this value.
360   NS_ASSERT (m_txParams.m_acknowledgment);
361 
362   if (m_txParams.m_acknowledgment->acknowledgmentTime == Time::Min ())
363     {
364       CalculateAcknowledgmentTime (m_txParams.m_acknowledgment.get ());
365     }
366 
367   // Set QoS Ack policy if this is a QoS data frame
368   WifiAckManager::SetQosAckPolicy (m_mpdu, m_txParams.m_acknowledgment.get ());
369 
370   switch (m_txParams.m_protection->method)
371     {
372     case WifiProtection::RTS_CTS:
373       SendRts (m_txParams);
374       break;
375     case WifiProtection::CTS_TO_SELF:
376       SendCtsToSelf (m_txParams);
377       break;
378     case WifiProtection::NONE:
379       SendMpdu ();
380       break;
381     default:
382       NS_ABORT_MSG ("Unknown protection type");
383     }
384 }
385 
386 void
SendMpdu(void)387 FrameExchangeManager::SendMpdu (void)
388 {
389   NS_LOG_FUNCTION (this);
390 
391   Time txDuration = m_phy->CalculateTxDuration (m_mpdu->GetSize (), m_txParams.m_txVector, m_phy->GetPhyBand ());
392 
393   NS_ASSERT (m_txParams.m_acknowledgment);
394 
395   if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NONE)
396     {
397       Simulator::Schedule (txDuration, &FrameExchangeManager::TransmissionSucceeded, this);
398 
399       if (!m_mpdu->GetHeader ().IsQosData ()
400           || m_mpdu->GetHeader ().GetQosAckPolicy () == WifiMacHeader::NO_ACK)
401         {
402           // No acknowledgment, hence dequeue the MPDU if it is stored in a queue
403           DequeueMpdu (m_mpdu);
404         }
405     }
406   else if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
407     {
408       m_mpdu->GetHeader ().SetDuration (GetFrameDurationId (m_mpdu->GetHeader (), m_mpdu->GetSize (),
409                                                             m_txParams, m_fragmentedPacket));
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);
420       NS_ASSERT (!m_txTimer.IsRunning ());
421       m_txTimer.Set (WifiTxTimer::WAIT_NORMAL_ACK, timeout, &FrameExchangeManager::NormalAckTimeout,
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
432   ForwardMpduDown (m_mpdu, m_txParams.m_txVector);
433 
434   if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NONE)
435     {
436       // we are done with frames that do not require acknowledgment
437       m_mpdu = 0;
438     }
439 }
440 
441 void
ForwardMpduDown(Ptr<WifiMacQueueItem> mpdu,WifiTxVector & txVector)442 FrameExchangeManager::ForwardMpduDown (Ptr<WifiMacQueueItem> mpdu, WifiTxVector& txVector)
443 {
444   NS_LOG_FUNCTION (this << *mpdu << txVector);
445 
446   m_phy->Send (Create<WifiPsdu> (mpdu, false), txVector);
447 }
448 
449 void
DequeueMpdu(Ptr<const WifiMacQueueItem> mpdu)450 FrameExchangeManager::DequeueMpdu (Ptr<const WifiMacQueueItem> mpdu)
451 {
452   NS_LOG_DEBUG (this << *mpdu);
453 
454   if (mpdu->IsQueued ())
455     {
456       m_mac->GetTxopQueue (mpdu->GetQueueAc ())->DequeueIfQueued (mpdu);
457     }
458 }
459 
460 void
CalculateProtectionTime(WifiProtection * protection) const461 FrameExchangeManager::CalculateProtectionTime (WifiProtection* protection) const
462 {
463   NS_LOG_FUNCTION (this << protection);
464   NS_ASSERT (protection != nullptr);
465 
466   if (protection->method == WifiProtection::NONE)
467     {
468       protection->protectionTime = Seconds (0);
469     }
470   else if (protection->method == WifiProtection::RTS_CTS)
471     {
472       WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (protection);
473       rtsCtsProtection->protectionTime = m_phy->CalculateTxDuration (GetRtsSize (), rtsCtsProtection->rtsTxVector,
474                                                                      m_phy->GetPhyBand ())
475                                          + m_phy->CalculateTxDuration (GetCtsSize (), rtsCtsProtection->ctsTxVector,
476                                                                        m_phy->GetPhyBand ())
477                                          + 2 * m_phy->GetSifs ();
478     }
479   else if (protection->method == WifiProtection::CTS_TO_SELF)
480     {
481       WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (protection);
482       ctsToSelfProtection->protectionTime = m_phy->CalculateTxDuration (GetCtsSize (),
483                                                                         ctsToSelfProtection->ctsTxVector,
484                                                                         m_phy->GetPhyBand ())
485                                             + m_phy->GetSifs ();
486     }
487 }
488 
489 void
CalculateAcknowledgmentTime(WifiAcknowledgment * acknowledgment) const490 FrameExchangeManager::CalculateAcknowledgmentTime (WifiAcknowledgment* acknowledgment) const
491 {
492   NS_LOG_FUNCTION (this << acknowledgment);
493   NS_ASSERT (acknowledgment != nullptr);
494 
495   if (acknowledgment->method == WifiAcknowledgment::NONE)
496     {
497       acknowledgment->acknowledgmentTime = Seconds (0);
498     }
499   else if (acknowledgment->method == WifiAcknowledgment::NORMAL_ACK)
500     {
501       WifiNormalAck* normalAcknowledgment = static_cast<WifiNormalAck*> (acknowledgment);
502       normalAcknowledgment->acknowledgmentTime = m_phy->GetSifs ()
503                                                  + m_phy->CalculateTxDuration (GetAckSize (),
504                                                                                normalAcknowledgment->ackTxVector,
505                                                                                m_phy->GetPhyBand ());
506     }
507 }
508 
509 Time
GetTxDuration(uint32_t ppduPayloadSize,Mac48Address receiver,const WifiTxParameters & txParams) const510 FrameExchangeManager::GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
511                                      const WifiTxParameters& txParams) const
512 {
513   return m_phy->CalculateTxDuration (ppduPayloadSize, txParams.m_txVector, m_phy->GetPhyBand ());
514 }
515 
516 void
UpdateTxDuration(Mac48Address receiver,WifiTxParameters & txParams) const517 FrameExchangeManager::UpdateTxDuration (Mac48Address receiver, WifiTxParameters& txParams) const
518 {
519   txParams.m_txDuration = GetTxDuration (txParams.GetSize (receiver), receiver, txParams);
520 }
521 
522 Time
GetFrameDurationId(const WifiMacHeader & header,uint32_t size,const WifiTxParameters & txParams,Ptr<Packet> fragmentedPacket) const523 FrameExchangeManager::GetFrameDurationId (const WifiMacHeader& header, uint32_t size,
524                                           const WifiTxParameters& txParams,
525                                           Ptr<Packet> fragmentedPacket) const
526 {
527   NS_LOG_FUNCTION (this << header << size << &txParams << fragmentedPacket);
528 
529   NS_ASSERT (txParams.m_acknowledgment && txParams.m_acknowledgment->acknowledgmentTime != Time::Min ());
530   Time durationId = txParams.m_acknowledgment->acknowledgmentTime;
531 
532   // if the current frame is a fragment followed by another fragment, we have to
533   // update the Duration/ID to cover the next fragment and the corresponding Ack
534   if (header.IsMoreFragments ())
535     {
536       uint32_t payloadSize = size - header.GetSize () - WIFI_MAC_FCS_LENGTH;
537       uint32_t nextFragmentOffset = (header.GetFragmentNumber () + 1) * payloadSize;
538       uint32_t nextFragmentSize = std::min (fragmentedPacket->GetSize () - nextFragmentOffset,
539                                             payloadSize);
540       WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (header.GetAddr1 (),
541                                                                                         txParams.m_txVector);
542 
543       durationId += 2 * m_phy->GetSifs ()
544                     + m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ())
545                     + m_phy->CalculateTxDuration (nextFragmentSize, txParams.m_txVector, m_phy->GetPhyBand ());
546     }
547   return durationId;
548 }
549 
550 Time
GetRtsDurationId(const WifiTxVector & rtsTxVector,Time txDuration,Time response) const551 FrameExchangeManager::GetRtsDurationId (const WifiTxVector& rtsTxVector, Time txDuration, Time response) const
552 {
553   NS_LOG_FUNCTION (this << rtsTxVector << txDuration << response);
554 
555   WifiTxVector ctsTxVector;
556   ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (m_self, rtsTxVector.GetMode ());
557 
558   return m_phy->GetSifs ()
559          + m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ()) /* CTS */
560          + m_phy->GetSifs () + txDuration + response;
561 }
562 
563 void
SendRts(const WifiTxParameters & txParams)564 FrameExchangeManager::SendRts (const WifiTxParameters& txParams)
565 {
566   NS_LOG_FUNCTION (this << &txParams);
567 
568   NS_ASSERT (txParams.GetPsduInfoMap ().size () == 1);
569   Mac48Address receiver = txParams.GetPsduInfoMap ().begin ()->first;
570 
571   WifiMacHeader rts;
572   rts.SetType (WIFI_MAC_CTL_RTS);
573   rts.SetDsNotFrom ();
574   rts.SetDsNotTo ();
575   rts.SetNoRetry ();
576   rts.SetNoMoreFragments ();
577   rts.SetAddr1 (receiver);
578   rts.SetAddr2 (m_self);
579 
580   NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS);
581   WifiRtsCtsProtection* rtsCtsProtection = static_cast<WifiRtsCtsProtection*> (txParams.m_protection.get ());
582 
583   NS_ASSERT (txParams.m_txDuration != Time::Min ());
584   rts.SetDuration (GetRtsDurationId (rtsCtsProtection->rtsTxVector, txParams.m_txDuration,
585                                       txParams.m_acknowledgment->acknowledgmentTime));
586   Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (Create<Packet> (), rts);
587 
588   // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
589   // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
590   // aRxPHYStartDelay equals the time to transmit the PHY header.
591   Time timeout = m_phy->CalculateTxDuration (GetRtsSize (), rtsCtsProtection->rtsTxVector, m_phy->GetPhyBand ())
592                  + m_phy->GetSifs ()
593                  + m_phy->GetSlot ()
594                  + m_phy->CalculatePhyPreambleAndHeaderDuration (rtsCtsProtection->ctsTxVector);
595   NS_ASSERT (!m_txTimer.IsRunning ());
596   m_txTimer.Set (WifiTxTimer::WAIT_CTS, timeout, &FrameExchangeManager::CtsTimeout, this,
597                  mpdu, rtsCtsProtection->rtsTxVector);
598   m_channelAccessManager->NotifyCtsTimeoutStartNow (timeout);
599 
600   ForwardMpduDown (mpdu, rtsCtsProtection->rtsTxVector);
601 }
602 
603 void
DoSendCtsAfterRts(const WifiMacHeader & rtsHdr,WifiTxVector & ctsTxVector,double rtsSnr)604 FrameExchangeManager::DoSendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiTxVector& ctsTxVector,
605                                          double rtsSnr)
606 {
607   NS_LOG_FUNCTION (this << rtsHdr << ctsTxVector << rtsSnr);
608 
609   WifiMacHeader cts;
610   cts.SetType (WIFI_MAC_CTL_CTS);
611   cts.SetDsNotFrom ();
612   cts.SetDsNotTo ();
613   cts.SetNoMoreFragments ();
614   cts.SetNoRetry ();
615   cts.SetAddr1 (rtsHdr.GetAddr2 ());
616   Time duration = rtsHdr.GetDuration () - m_phy->GetSifs ()
617                   - m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
618   // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
619   if (duration.IsStrictlyNegative ())
620     {
621       duration = Seconds (0);
622     }
623   cts.SetDuration (duration);
624 
625   Ptr<Packet> packet = Create<Packet> ();
626 
627   SnrTag tag;
628   tag.Set (rtsSnr);
629   packet->AddPacketTag (tag);
630 
631   // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
632   ForwardMpduDown (Create<WifiMacQueueItem> (packet, cts), ctsTxVector);
633 }
634 
635 void
SendCtsAfterRts(const WifiMacHeader & rtsHdr,WifiMode rtsTxMode,double rtsSnr)636 FrameExchangeManager::SendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiMode rtsTxMode, double rtsSnr)
637 {
638   NS_LOG_FUNCTION (this << rtsHdr << rtsTxMode << rtsSnr);
639 
640   WifiTxVector ctsTxVector = m_mac->GetWifiRemoteStationManager ()->GetCtsTxVector (rtsHdr.GetAddr2 (), rtsTxMode);
641   DoSendCtsAfterRts (rtsHdr, ctsTxVector, rtsSnr);
642 }
643 
644 Time
GetCtsToSelfDurationId(const WifiTxVector & ctsTxVector,Time txDuration,Time response) const645 FrameExchangeManager::GetCtsToSelfDurationId (const WifiTxVector& ctsTxVector,
646                                                Time txDuration, Time response) const
647 {
648   NS_LOG_FUNCTION (this << ctsTxVector << txDuration << response);
649 
650   return m_phy->GetSifs () + txDuration + response;
651 }
652 
653 void
SendCtsToSelf(const WifiTxParameters & txParams)654 FrameExchangeManager::SendCtsToSelf (const WifiTxParameters& txParams)
655 {
656   NS_LOG_FUNCTION (this << &txParams);
657 
658   WifiMacHeader cts;
659   cts.SetType (WIFI_MAC_CTL_CTS);
660   cts.SetDsNotFrom ();
661   cts.SetDsNotTo ();
662   cts.SetNoMoreFragments ();
663   cts.SetNoRetry ();
664   cts.SetAddr1 (m_self);
665 
666   NS_ASSERT (txParams.m_protection && txParams.m_protection->method == WifiProtection::CTS_TO_SELF);
667   WifiCtsToSelfProtection* ctsToSelfProtection = static_cast<WifiCtsToSelfProtection*> (txParams.m_protection.get ());
668 
669   NS_ASSERT (txParams.m_txDuration != Time::Min ());
670   cts.SetDuration (GetCtsToSelfDurationId (ctsToSelfProtection->ctsTxVector, txParams.m_txDuration,
671                                             txParams.m_acknowledgment->acknowledgmentTime));
672 
673   ForwardMpduDown (Create<WifiMacQueueItem> (Create<Packet> (), cts), ctsToSelfProtection->ctsTxVector);
674 
675   Time ctsDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsToSelfProtection->ctsTxVector,
676                                                  m_phy->GetPhyBand ());
677   Simulator::Schedule (ctsDuration + m_phy->GetSifs (), &FrameExchangeManager::SendMpdu, this);
678 }
679 
680 void
SendNormalAck(const WifiMacHeader & hdr,const WifiTxVector & dataTxVector,double dataSnr)681 FrameExchangeManager::SendNormalAck (const WifiMacHeader& hdr, const WifiTxVector& dataTxVector,
682                                      double dataSnr)
683 {
684   NS_LOG_FUNCTION (this << hdr << dataTxVector << dataSnr);
685 
686   WifiTxVector ackTxVector = m_mac->GetWifiRemoteStationManager ()->GetAckTxVector (hdr.GetAddr2 (), dataTxVector);
687   WifiMacHeader ack;
688   ack.SetType (WIFI_MAC_CTL_ACK);
689   ack.SetDsNotFrom ();
690   ack.SetDsNotTo ();
691   ack.SetNoRetry ();
692   ack.SetNoMoreFragments ();
693   ack.SetAddr1 (hdr.GetAddr2 ());
694   // 802.11-2016, Section 9.2.5.7: Duration/ID is received duration value
695   // minus the time to transmit the Ack frame and its SIFS interval
696   Time duration = hdr.GetDuration () - m_phy->GetSifs ()
697                   - m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ());
698   // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8 of 802.11-2016)
699   if (duration.IsStrictlyNegative ())
700     {
701       duration = Seconds (0);
702     }
703   ack.SetDuration (duration);
704 
705   Ptr<Packet> packet = Create<Packet> ();
706 
707   SnrTag tag;
708   tag.Set (dataSnr);
709   packet->AddPacketTag (tag);
710 
711   ForwardMpduDown (Create<WifiMacQueueItem> (packet, ack), ackTxVector);
712 }
713 
714 Ptr<WifiMacQueueItem>
GetNextFragment(void)715 FrameExchangeManager::GetNextFragment (void)
716 {
717   NS_LOG_FUNCTION (this);
718   NS_ASSERT (m_mpdu->GetHeader ().IsMoreFragments ());
719 
720   WifiMacHeader& hdr = m_mpdu->GetHeader ();
721   hdr.SetFragmentNumber (hdr.GetFragmentNumber () + 1);
722 
723   uint32_t startOffset = hdr.GetFragmentNumber () * m_mpdu->GetPacketSize ();
724   uint32_t size = m_fragmentedPacket->GetSize () - startOffset;
725 
726   if (size > m_mpdu->GetPacketSize ())
727     {
728       // this is not the last fragment
729       size = m_mpdu->GetPacketSize ();
730       hdr.SetMoreFragments ();
731     }
732   else
733     {
734       hdr.SetNoMoreFragments ();
735     }
736 
737   return Create<WifiMacQueueItem> (m_fragmentedPacket->CreateFragment (startOffset, size), hdr);
738 }
739 
740 void
TransmissionSucceeded(void)741 FrameExchangeManager::TransmissionSucceeded (void)
742 {
743   NS_LOG_FUNCTION (this);
744 
745   // Upon a transmission success, a non-QoS station transmits the next fragment,
746   // if any, or releases the channel, otherwise
747   if (m_moreFragments)
748     {
749       NS_LOG_DEBUG ("Schedule transmission of next fragment in a SIFS");
750       Simulator::Schedule (m_phy->GetSifs (), &FrameExchangeManager::StartTransmission, this, m_dcf);
751       m_moreFragments = false;
752     }
753   else
754     {
755       m_dcf->NotifyChannelReleased ();
756       m_dcf = 0;
757     }
758 }
759 
760 void
TransmissionFailed(void)761 FrameExchangeManager::TransmissionFailed (void)
762 {
763   NS_LOG_FUNCTION (this);
764   // A non-QoS station always releases the channel upon a transmission failure
765   m_dcf->NotifyChannelReleased ();
766   m_dcf = 0;
767 }
768 
769 void
NormalAckTimeout(Ptr<WifiMacQueueItem> mpdu,const WifiTxVector & txVector)770 FrameExchangeManager::NormalAckTimeout (Ptr<WifiMacQueueItem> mpdu, const WifiTxVector& txVector)
771 {
772   NS_LOG_FUNCTION (this << *mpdu << txVector);
773 
774   m_mac->GetWifiRemoteStationManager ()->ReportDataFailed (mpdu);
775 
776   if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
777     {
778       NS_LOG_DEBUG ("Missed Ack, discard MPDU");
779       NotifyPacketDiscarded (mpdu);
780       // Dequeue the MPDU if it is stored in a queue
781       DequeueMpdu (mpdu);
782       m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
783       m_dcf->ResetCw ();
784     }
785   else
786     {
787       NS_LOG_DEBUG ("Missed Ack, retransmit MPDU");
788       mpdu->GetHeader ().SetRetry ();
789       RetransmitMpduAfterMissedAck (mpdu);
790       m_dcf->UpdateFailedCw ();
791     }
792 
793   m_mpdu = 0;
794   TransmissionFailed ();
795 }
796 
797 void
RetransmitMpduAfterMissedAck(Ptr<WifiMacQueueItem> mpdu) const798 FrameExchangeManager::RetransmitMpduAfterMissedAck (Ptr<WifiMacQueueItem> mpdu) const
799 {
800   NS_LOG_FUNCTION (this << *mpdu);
801 }
802 
803 void
CtsTimeout(Ptr<WifiMacQueueItem> rts,const WifiTxVector & txVector)804 FrameExchangeManager::CtsTimeout (Ptr<WifiMacQueueItem> rts, const WifiTxVector& txVector)
805 {
806   NS_LOG_FUNCTION (this << *rts << txVector);
807 
808   m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_mpdu->GetHeader ());
809 
810   if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (m_mpdu))
811     {
812       NS_LOG_DEBUG ("Missed CTS, discard MPDU");
813       // Dequeue the MPDU if it is stored in a queue
814       DequeueMpdu (m_mpdu);
815       NotifyPacketDiscarded (m_mpdu);
816       m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (m_mpdu->GetHeader ());
817       m_dcf->ResetCw ();
818     }
819   else
820     {
821       NS_LOG_DEBUG ("Missed CTS, retransmit RTS");
822       RetransmitMpduAfterMissedCts (m_mpdu);
823       m_dcf->UpdateFailedCw ();
824     }
825   m_mpdu = 0;
826   TransmissionFailed ();
827 }
828 
829 void
RetransmitMpduAfterMissedCts(Ptr<WifiMacQueueItem> mpdu) const830 FrameExchangeManager::RetransmitMpduAfterMissedCts (Ptr<WifiMacQueueItem> mpdu) const
831 {
832   NS_LOG_FUNCTION (this << *mpdu);
833 
834   // the MPDU should be still in the DCF queue, unless it expired.
835   // If the MPDU has never been transmitted, it will be assigned a sequence
836   // number again the next time we try to transmit it. Therefore, we need to
837   // make its sequence number available again
838   if (!mpdu->GetHeader ().IsRetry ())
839     {
840       m_txMiddle->SetSequenceNumberFor (&mpdu->GetHeader ());
841     }
842 }
843 
844 void
NotifyInternalCollision(Ptr<Txop> txop)845 FrameExchangeManager::NotifyInternalCollision (Ptr<Txop> txop)
846 {
847   NS_LOG_FUNCTION (this);
848 
849   // For internal collisions occurring with the EDCA access method, the appropriate
850   // retry counters (short retry counter for MSDU, A-MSDU, or MMPDU and QSRC[AC] or
851   // long retry counter for MSDU, A-MSDU, or MMPDU and QLRC[AC]) are incremented
852   // (Sec. 10.22.2.11.1 of 802.11-2016).
853   // We do not prepare the PSDU that the AC losing the internal collision would have
854   // sent. As an approximation, we consider the frame peeked from the queues of the AC.
855   Ptr<QosTxop> qosTxop = (txop->IsQosTxop () ? StaticCast<QosTxop> (txop) : nullptr);
856 
857   Ptr<const WifiMacQueueItem> mpdu = (qosTxop != nullptr ? qosTxop->PeekNextMpdu ()
858                                                          : txop->GetWifiMacQueue ()->Peek ());
859 
860   if (mpdu != nullptr)
861     {
862       m_mac->GetWifiRemoteStationManager ()->ReportDataFailed (mpdu);
863 
864       if (!mpdu->GetHeader ().GetAddr1 ().IsGroup ()
865           && !m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (mpdu))
866         {
867           NS_LOG_DEBUG ("reset DCF");
868           m_mac->GetWifiRemoteStationManager ()->ReportFinalDataFailed (mpdu);
869           DequeueMpdu (mpdu);
870           NotifyPacketDiscarded (mpdu);
871           txop->ResetCw ();
872         }
873       else
874         {
875           NS_LOG_DEBUG ("Update CW");
876           txop->UpdateFailedCw ();
877         }
878     }
879 
880   txop->Txop::NotifyChannelReleased ();
881 }
882 
883 void
NotifySwitchingStartNow(Time duration)884 FrameExchangeManager::NotifySwitchingStartNow (Time duration)
885 {
886   NS_LOG_DEBUG ("Switching channel. Cancelling MAC pending events");
887   m_mac->GetWifiRemoteStationManager ()->Reset ();
888   Reset ();
889 }
890 
891 void
NotifySleepNow(void)892 FrameExchangeManager::NotifySleepNow (void)
893 {
894   NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
895   Reset ();
896 }
897 
898 void
NotifyOffNow(void)899 FrameExchangeManager::NotifyOffNow (void)
900 {
901   NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
902   Reset ();
903 }
904 
905 void
Receive(Ptr<WifiPsdu> psdu,RxSignalInfo rxSignalInfo,WifiTxVector txVector,std::vector<bool> perMpduStatus)906 FrameExchangeManager::Receive (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
907                                WifiTxVector txVector, std::vector<bool> perMpduStatus)
908 {
909   NS_LOG_FUNCTION (this << psdu << rxSignalInfo << txVector << perMpduStatus.size ()
910                    << std::all_of (perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
911 
912   if (!perMpduStatus.empty ())
913     {
914       // for A-MPDUs, we get here only once
915       PreProcessFrame (psdu, txVector);
916     }
917 
918   // ignore unicast frames that are not addressed to us
919   Mac48Address addr1 = psdu->GetAddr1 ();
920   if (!addr1.IsGroup () && addr1 != m_self)
921     {
922       if (m_promisc && psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsData ())
923         {
924           m_rxMiddle->Receive (*psdu->begin ());
925         }
926       return;
927     }
928 
929   if (psdu->GetNMpdus () == 1)
930     {
931       // if perMpduStatus is not empty (i.e., this MPDU is not included in an A-MPDU)
932       // then it must contain a single value which must be true (i.e., the MPDU
933       // has been correctly received)
934       NS_ASSERT (perMpduStatus.empty () || (perMpduStatus.size () == 1 && perMpduStatus[0]));
935       // Ack and CTS do not carry Addr2
936       if (!psdu->GetHeader (0).IsAck () && !psdu->GetHeader (0).IsCts ())
937         {
938           m_mac->GetWifiRemoteStationManager ()->ReportRxOk (psdu->GetHeader (0).GetAddr2 (),
939                                                              rxSignalInfo, txVector);
940         }
941       ReceiveMpdu (*(psdu->begin ()), rxSignalInfo, txVector, perMpduStatus.empty ());
942     }
943   else
944     {
945       EndReceiveAmpdu (psdu, rxSignalInfo, txVector, perMpduStatus);
946     }
947 }
948 
949 void
PreProcessFrame(Ptr<const WifiPsdu> psdu,const WifiTxVector & txVector)950 FrameExchangeManager::PreProcessFrame (Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector)
951 {
952   NS_LOG_FUNCTION (this << psdu << txVector);
953 
954   UpdateNav (psdu, txVector);
955 }
956 
957 void
UpdateNav(Ptr<const WifiPsdu> psdu,const WifiTxVector & txVector)958 FrameExchangeManager::UpdateNav (Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector)
959 {
960   NS_LOG_FUNCTION (this << psdu << txVector);
961 
962   if (psdu->GetHeader (0).GetRawDuration () > 32767)
963     {
964       // When the contents of a received Duration/ID field, treated as an unsigned
965       // integer, are greater than 32 768, the contents are interpreted as appropriate
966       // for the frame type and subtype or ignored if the receiving MAC entity does
967       // not have a defined interpretation for that type and subtype (IEEE 802.11-2016
968       // sec. 10.27.3)
969       return;
970     }
971 
972   Time duration = psdu->GetDuration ();
973   NS_LOG_DEBUG ("Duration/ID=" << duration);
974 
975   if (psdu->GetAddr1 () == m_self)
976     {
977       // When the received frame’s RA is equal to the STA’s own MAC address, the STA
978       // shall not update its NAV (IEEE 802.11-2016, sec. 10.3.2.4)
979       return;
980     }
981 
982   // For all other received frames the STA shall update its NAV when the received
983   // Duration is greater than the STA’s current NAV value (IEEE 802.11-2016 sec. 10.3.2.4)
984   Time navEnd = Simulator::Now () + duration;
985   if (navEnd > m_navEnd)
986     {
987       m_navEnd = navEnd;
988       NS_LOG_DEBUG ("Updated NAV=" << m_navEnd);
989 
990       // A STA that used information from an RTS frame as the most recent basis to update
991       // its NAV setting is permitted to reset its NAV if no PHY-RXSTART.indication
992       // primitive is received from the PHY during a NAVTimeout period starting when the
993       // MAC receives a PHY-RXEND.indication primitive corresponding to the detection of
994       // the RTS frame. NAVTimeout period is equal to:
995       // (2 x aSIFSTime) + (CTS_Time) + aRxPHYStartDelay + (2 x aSlotTime)
996       // The “CTS_Time” shall be calculated using the length of the CTS frame and the data
997       // rate at which the RTS frame used for the most recent NAV update was received
998       // (IEEE 802.11-2016 sec. 10.3.2.4)
999       if (psdu->GetHeader (0).IsRts ())
1000         {
1001           Time navResetDelay = 2 * m_phy->GetSifs ()
1002                                + WifiPhy::CalculateTxDuration (GetCtsSize (), txVector,
1003                                                                m_phy->GetPhyBand ())
1004                                + m_phy->CalculatePhyPreambleAndHeaderDuration (txVector)
1005                                + 2 * m_phy->GetSlot ();
1006           m_navResetEvent = Simulator::Schedule (navResetDelay, &FrameExchangeManager::NavResetTimeout, this);
1007         }
1008     }
1009   NS_LOG_DEBUG ("Current NAV=" << m_navEnd);
1010 
1011   m_channelAccessManager->NotifyNavStartNow (duration);
1012 }
1013 
1014 void
NavResetTimeout(void)1015 FrameExchangeManager::NavResetTimeout (void)
1016 {
1017   NS_LOG_FUNCTION (this);
1018   m_navEnd = Simulator::Now ();
1019   m_channelAccessManager->NotifyNavResetNow (Seconds (0));
1020 }
1021 
1022 void
ReceiveMpdu(Ptr<WifiMacQueueItem> mpdu,RxSignalInfo rxSignalInfo,const WifiTxVector & txVector,bool inAmpdu)1023 FrameExchangeManager::ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rxSignalInfo,
1024                                    const WifiTxVector& txVector, bool inAmpdu)
1025 {
1026   NS_LOG_FUNCTION (this << *mpdu << rxSignalInfo << txVector << inAmpdu);
1027   // The received MPDU is either broadcast or addressed to this station
1028   NS_ASSERT (mpdu->GetHeader ().GetAddr1 ().IsGroup ()
1029              || mpdu->GetHeader ().GetAddr1 () == m_self);
1030 
1031   double rxSnr = rxSignalInfo.snr;
1032   const WifiMacHeader& hdr = mpdu->GetHeader ();
1033 
1034   if (hdr.IsCtl ())
1035     {
1036       if (hdr.IsRts ())
1037         {
1038           NS_ABORT_MSG_IF (inAmpdu, "Received RTS as part of an A-MPDU");
1039 
1040           // A non-VHT STA that is addressed by an RTS frame behaves as follows:
1041           // - If the NAV indicates idle, the STA shall respond with a CTS frame after a SIFS
1042           // - Otherwise, the STA shall not respond with a CTS frame
1043           // (IEEE 802.11-2016 sec. 10.3.2.7)
1044           if (m_navEnd <= Simulator::Now ())
1045             {
1046               NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
1047               Simulator::Schedule (m_phy->GetSifs (), &FrameExchangeManager::SendCtsAfterRts,
1048                                    this, hdr, txVector.GetMode (), rxSnr);
1049             }
1050           else
1051             {
1052               NS_LOG_DEBUG ("Received RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
1053             }
1054         }
1055       else if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS
1056                && m_mpdu != 0)
1057         {
1058           NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU");
1059           NS_ASSERT (hdr.GetAddr1 () == m_self);
1060 
1061           Mac48Address sender = m_mpdu->GetHeader ().GetAddr1 ();
1062           NS_LOG_DEBUG ("Received CTS from=" << sender);
1063 
1064           SnrTag tag;
1065           mpdu->GetPacket ()->PeekPacketTag (tag);
1066           m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector);
1067           m_mac->GetWifiRemoteStationManager ()->ReportRtsOk (m_mpdu->GetHeader (),
1068                                                               rxSnr, txVector.GetMode (), tag.Get ());
1069 
1070           m_txTimer.Cancel ();
1071           m_channelAccessManager->NotifyCtsTimeoutResetNow ();
1072           Simulator::Schedule (m_phy->GetSifs (), &FrameExchangeManager::SendMpdu, this);
1073         }
1074       else if (hdr.IsAck () && m_mpdu != 0 && m_txTimer.IsRunning ()
1075                && m_txTimer.GetReason () == WifiTxTimer::WAIT_NORMAL_ACK)
1076         {
1077           NS_ASSERT (hdr.GetAddr1 () == m_self);
1078           SnrTag tag;
1079           mpdu->GetPacket ()->PeekPacketTag (tag);
1080           ReceivedNormalAck (m_mpdu, m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ());
1081           m_mpdu = 0;
1082         }
1083     }
1084   else if (hdr.IsMgt ())
1085     {
1086       NS_ABORT_MSG_IF (inAmpdu, "Received management frame as part of an A-MPDU");
1087 
1088       if (hdr.IsBeacon () || hdr.IsProbeResp ())
1089         {
1090           // Apply SNR tag for beacon quality measurements
1091           SnrTag tag;
1092           tag.Set (rxSnr);
1093           Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
1094           packet->AddPacketTag (tag);
1095           mpdu = Create<WifiMacQueueItem> (packet, hdr);
1096         }
1097 
1098       if (hdr.GetAddr1 () == m_self)
1099         {
1100           NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1101           Simulator::Schedule (m_phy->GetSifs (), &FrameExchangeManager::SendNormalAck,
1102                                this, hdr, txVector, rxSnr);
1103         }
1104 
1105       m_rxMiddle->Receive (mpdu);
1106     }
1107   else if (hdr.IsData () && !hdr.IsQosData ())
1108     {
1109       if (hdr.GetAddr1 () == m_self)
1110         {
1111           NS_LOG_DEBUG ("Received " << hdr.GetTypeString () << " from=" << hdr.GetAddr2 () << ", schedule ACK");
1112           Simulator::Schedule (m_phy->GetSifs (), &FrameExchangeManager::SendNormalAck,
1113                                this, hdr, txVector, rxSnr);
1114         }
1115 
1116       m_rxMiddle->Receive (mpdu);
1117     }
1118 }
1119 
1120 void
ReceivedNormalAck(Ptr<WifiMacQueueItem> mpdu,const WifiTxVector & txVector,const WifiTxVector & ackTxVector,const RxSignalInfo & rxInfo,double snr)1121 FrameExchangeManager::ReceivedNormalAck (Ptr<WifiMacQueueItem> mpdu, const WifiTxVector& txVector,
1122                                          const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo,
1123                                          double snr)
1124 {
1125   Mac48Address sender = mpdu->GetHeader ().GetAddr1 ();
1126   NS_LOG_DEBUG ("Received ACK from=" << sender);
1127 
1128   NotifyReceivedNormalAck (mpdu);
1129 
1130   // When fragmentation is used, only update manager when the last fragment is acknowledged
1131   if (!mpdu->GetHeader ().IsMoreFragments ())
1132     {
1133       m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxInfo, ackTxVector);
1134       m_mac->GetWifiRemoteStationManager ()->ReportDataOk (mpdu, rxInfo.snr, ackTxVector.GetMode (),
1135                                                            snr, txVector);
1136     }
1137   // cancel the timer
1138   m_txTimer.Cancel ();
1139   m_channelAccessManager->NotifyAckTimeoutResetNow ();
1140 
1141   // The CW shall be reset to aCWmin after every successful attempt to transmit
1142   // a frame containing all or part of an MSDU or MMPDU (sec. 10.3.3 of 802.11-2016)
1143   m_dcf->ResetCw ();
1144 
1145   // The MPDU has been acknowledged, we can now dequeue it if it is stored in a queue
1146   DequeueMpdu (mpdu);
1147 
1148   if (mpdu->GetHeader ().IsMoreFragments ())
1149     {
1150       // enqueue the next fragment
1151       Ptr<WifiMacQueueItem> next = GetNextFragment ();
1152       m_dcf->GetWifiMacQueue ()->PushFront (next);
1153       m_moreFragments = true;
1154     }
1155 
1156   TransmissionSucceeded ();
1157 }
1158 
1159 void
NotifyReceivedNormalAck(Ptr<WifiMacQueueItem> mpdu)1160 FrameExchangeManager::NotifyReceivedNormalAck (Ptr<WifiMacQueueItem> mpdu)
1161 {
1162   NS_LOG_FUNCTION (this << *mpdu);
1163 
1164   // inform the MAC that the transmission was successful
1165   if (!m_ackedMpduCallback.IsNull ())
1166     {
1167       m_ackedMpduCallback (mpdu);
1168     }
1169 }
1170 
1171 void
EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,const RxSignalInfo & rxSignalInfo,const WifiTxVector & txVector,const std::vector<bool> & perMpduStatus)1172 FrameExchangeManager::EndReceiveAmpdu (Ptr<const WifiPsdu> psdu, const RxSignalInfo& rxSignalInfo,
1173                                        const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus)
1174 {
1175   NS_ASSERT_MSG (false, "A non-QoS station should not receive an A-MPDU");
1176 }
1177 
1178 } //namespace ns3
1179