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