A Discrete-Event Network Simulator
API
mac-low.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Mirko Banchi <mk.banchi@gmail.com>
21  */
22 
23 #include "ns3/simulator.h"
24 #include "ns3/log.h"
25 #include "ns3/socket.h"
26 #include "mac-low.h"
27 #include "qos-txop.h"
28 #include "snr-tag.h"
29 #include "ampdu-tag.h"
30 #include "wifi-mac-queue.h"
31 #include "wifi-utils.h"
32 #include "ctrl-headers.h"
33 #include "mgt-headers.h"
35 #include "mpdu-aggregator.h"
36 #include "msdu-aggregator.h"
37 #include "ampdu-subframe-header.h"
38 #include "wifi-phy-listener.h"
39 #include "wifi-mac-trailer.h"
40 #include "wifi-phy.h"
41 #include "wifi-net-device.h"
42 
43 #undef NS_LOG_APPEND_CONTEXT
44 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
45 
46 namespace ns3 {
47 
48 NS_LOG_COMPONENT_DEFINE ("MacLow");
49 
54 {
55 public:
62  : m_macLow (macLow)
63  {
64  }
65  virtual ~PhyMacLowListener ()
66  {
67  }
68  void NotifyRxStart (Time duration)
69  {
70  }
71  void NotifyRxEndOk (void)
72  {
73  }
74  void NotifyRxEndError (void)
75  {
76  }
77  void NotifyTxStart (Time duration, double txPowerDbm)
78  {
79  }
80  void NotifyMaybeCcaBusyStart (Time duration)
81  {
82  }
83  void NotifySwitchingStart (Time duration)
84  {
86  }
87  void NotifySleep (void)
88  {
90  }
91  void NotifyOff (void)
92  {
94  }
95  void NotifyWakeup (void)
96  {
97  }
98  void NotifyOn (void)
99  {
100  }
101 
102 private:
104 };
105 
106 
108  : m_normalAckTimeoutEvent (),
109  m_blockAckTimeoutEvent (),
110  m_ctsTimeoutEvent (),
111  m_sendCtsEvent (),
112  m_sendAckEvent (),
113  m_sendDataEvent (),
114  m_waitIfsEvent (),
115  m_endTxNoAckEvent (),
116  m_currentPacket (0),
117  m_currentTxop (0),
118  m_lastNavStart (Seconds (0)),
119  m_lastNavDuration (Seconds (0)),
120  m_cfpStart (Seconds (0)),
121  m_lastBeacon (Seconds (0)),
122  m_cfpForeshortening (Seconds (0)),
123  m_promisc (false),
124  m_ampdu (false),
125  m_phyMacLowListener (0),
126  m_ctsToSelfSupported (false),
127  m_cfAckInfo ()
128 {
129  NS_LOG_FUNCTION (this);
130  for (uint8_t i = 0; i < 8; i++)
131  {
132  m_aggregateQueue[i] = CreateObject<WifiMacQueue> ();
133  }
134 }
135 
137 {
138  NS_LOG_FUNCTION (this);
139 }
140 
141 /* static */
142 TypeId
144 {
145  static TypeId tid = TypeId ("ns3::MacLow")
146  .SetParent<Object> ()
147  .SetGroupName ("Wifi")
148  .AddConstructor<MacLow> ()
149  ;
150  return tid;
151 }
152 
153 void
155 {
158 }
159 
160 void
162 {
163  if (m_phyMacLowListener != 0 )
164  {
166  delete m_phyMacLowListener;
168  }
169 }
170 
171 void
173 {
174  NS_LOG_FUNCTION (this);
183  m_phy = 0;
184  m_stationManager = 0;
185  if (m_phyMacLowListener != 0)
186  {
187  delete m_phyMacLowListener;
189  }
190  for (uint8_t i = 0; i < 8; i++)
191  {
192  m_aggregateQueue[i] = 0;
193  }
194  m_ampdu = false;
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this);
201  bool oneRunning = false;
203  {
205  oneRunning = true;
206  }
208  {
210  oneRunning = true;
211  }
213  {
215  oneRunning = true;
216  }
217  if (m_sendCtsEvent.IsRunning ())
218  {
220  oneRunning = true;
221  }
222  if (m_sendAckEvent.IsRunning ())
223  {
225  oneRunning = true;
226  }
227  if (m_sendDataEvent.IsRunning ())
228  {
230  oneRunning = true;
231  }
232  if (m_waitIfsEvent.IsRunning ())
233  {
235  oneRunning = true;
236  }
238  {
240  oneRunning = true;
241  }
242  if (oneRunning && m_currentTxop != 0)
243  {
244  m_currentTxop->Cancel ();
245  m_currentTxop = 0;
246  }
247 }
248 
249 void
251 {
252  m_phy = phy;
256 }
257 
259 MacLow::GetPhy (void) const
260 {
261  return m_phy;
262 }
263 
264 void
266 {
270  m_phy = 0;
271 }
272 
273 void
275 {
276  m_stationManager = manager;
277 }
278 
279 void
281 {
282  m_self = ad;
283 }
284 
285 void
287 {
288  m_ackTimeout = ackTimeout;
289 }
290 
291 void
293 {
294  m_basicBlockAckTimeout = blockAckTimeout;
295 }
296 
297 void
299 {
300  m_compressedBlockAckTimeout = blockAckTimeout;
301 }
302 
303 void
305 {
306  m_ctsToSelfSupported = enable;
307 }
308 
309 bool
311 {
312  return m_ctsToSelfSupported;
313 }
314 
315 void
317 {
318  m_ctsTimeout = ctsTimeout;
319 }
320 
321 void
323 {
324  m_sifs = sifs;
325 }
326 
327 void
329 {
330  m_slotTime = slotTime;
331 }
332 
333 void
335 {
336  m_pifs = pifs;
337 }
338 
339 void
341 {
342  m_rifs = rifs;
343 }
344 
345 void
347 {
348  m_beaconInterval = interval;
349 }
350 
351 void
353 {
354  m_cfpMaxDuration = cfpMaxDuration;
355 }
356 
357 void
359 {
360  m_bssid = bssid;
361 }
362 
363 void
365 {
366  m_promisc = true;
367 }
368 
370 MacLow::GetAddress (void) const
371 {
372  return m_self;
373 }
374 
375 Time
377 {
378  return m_ackTimeout;
379 }
380 
381 Time
383 {
384  return m_basicBlockAckTimeout;
385 }
386 
387 Time
389 {
391 }
392 
393 Time
395 {
396  return m_ctsTimeout;
397 }
398 
399 Time
400 MacLow::GetSifs (void) const
401 {
402  NS_LOG_FUNCTION (this);
403  return m_sifs;
404 }
405 
406 Time
407 MacLow::GetRifs (void) const
408 {
409  NS_LOG_FUNCTION (this);
410  return m_rifs;
411 }
412 
413 Time
415 {
416  return m_slotTime;
417 }
418 
419 Time
420 MacLow::GetPifs (void) const
421 {
422  return m_pifs;
423 }
424 
426 MacLow::GetBssid (void) const
427 {
428  return m_bssid;
429 }
430 
431 Time
433 {
434  return m_beaconInterval;
435 }
436 
437 Time
439 {
440  return m_cfpMaxDuration;
441 }
442 
443 bool
444 MacLow::IsPromisc (void) const
445 {
446  return m_promisc;
447 }
448 
449 void
451 {
452  m_rxCallback = callback;
453 }
454 
455 void
457 {
458  m_channelAccessManagers.push_back (dcf);
459 }
460 
461 bool
463 {
464  uint32_t size, actualSize;
465  WifiMacTrailer fcs;
466  size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
467  Ptr<Packet> p = AggregateToAmpdu (packet, hdr);
468  actualSize = p->GetSize ();
469  if (actualSize > size)
470  {
471  m_currentPacket = p;
472  return true;
473  }
474  return false;
475 }
476 
477 void
479  const WifiMacHeader* hdr,
481  Ptr<Txop> txop)
482 {
483  NS_LOG_FUNCTION (this << packet << hdr << params << txop);
485  if (m_phy->IsStateOff ())
486  {
487  NS_LOG_DEBUG ("Cannot start TX because device is OFF");
488  return;
489  }
490  /* m_currentPacket is not NULL because someone started
491  * a transmission and was interrupted before one of:
492  * - ctsTimeout
493  * - sendDataAfterCTS
494  * expired. This means that one of these timers is still
495  * running. They are all cancelled below anyway by the
496  * call to CancelAllEvents (because of at least one
497  * of these two timers) which will trigger a call to the
498  * previous listener's cancel method.
499  *
500  * This typically happens because the high-priority
501  * QapScheduler has taken access to the channel from
502  * one of the Edca of the QAP.
503  */
504  m_currentPacket = packet->Copy ();
505  // remove the priority tag attached, if any
506  SocketPriorityTag priorityTag;
507  m_currentPacket->RemovePacketTag (priorityTag);
508  m_currentHdr = *hdr;
509  CancelAllEvents ();
510  m_currentTxop = txop;
511  m_txParams = params;
513 
514  if (NeedRts () && !IsCfPeriod ())
515  {
517  }
518  else
519  {
521  }
522 
523  if (m_currentHdr.IsMgt ()
524  || (!m_currentHdr.IsQosData ()
525  && !m_currentHdr.IsBlockAck ()
526  && !m_currentHdr.IsBlockAckReq ()))
527  {
528  //This is mainly encountered when a higher priority control or management frame is
529  //sent between A-MPDU transmissions. It avoids to unexpectedly flush the aggregate
530  //queue when previous RTS request has failed.
531  m_ampdu = false;
532  }
533  else if (m_currentHdr.IsQosData () && !m_aggregateQueue[GetTid (packet, *hdr)]->IsEmpty ())
534  {
535  //m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
536  //In that case, we transmit the same A-MPDU as previously.
537  uint32_t sentMpdus = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
538  m_ampdu = true;
539  if (sentMpdus > 1)
540  {
542  }
543  else if (m_currentHdr.IsQosData ())
544  {
545  //VHT/HE single MPDUs are followed by normal ACKs
547  }
548  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
549  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
550  Ptr<Packet> aggregatedPacket = Create<Packet> ();
551  for (uint32_t i = 0; i < sentMpdus; i++)
552  {
553  Ptr<Packet> newPacket = (m_txPackets[GetTid (packet, *hdr)].at (i).packet)->Copy ();
554  newPacket->AddHeader (m_txPackets[GetTid (packet, *hdr)].at (i).hdr);
555  AddWifiMacTrailer (newPacket);
556  edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, aggregatedPacket);
557  }
558  m_currentPacket = aggregatedPacket;
559  m_currentHdr = (m_txPackets[GetTid (packet, *hdr)].at (0).hdr);
561  }
562  else
563  {
564  //Perform MPDU aggregation if possible
566  if (m_ampdu)
567  {
568  AmpduTag ampdu;
570  if (ampdu.GetRemainingNbOfMpdus () > 0)
571  {
573  }
574  else if (m_currentHdr.IsQosData ())
575  {
576  //VHT/HE single MPDUs are followed by normal ACKs
578  }
579  }
580  }
581 
582  NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr, m_ampdu) <<
583  ", to=" << m_currentHdr.GetAddr1 () << ", txop=" << m_currentTxop);
584 
585  if (m_txParams.MustSendRts ())
586  {
587  SendRtsForPacket ();
588  }
589  else
590  {
592  {
593  SendCtsToSelf ();
594  }
595  else
596  {
597  SendDataPacket ();
598  }
599  }
600 
601  /* When this method completes, either we have taken ownership of the medium or the device switched off in the meantime. */
603 }
604 
605 bool
606 MacLow::NeedRts (void) const
607 {
610  m_currentPacket, dataTxVector);
611 }
612 
613 bool
615 {
617  return m_stationManager->NeedCtsToSelf (dataTxVector);
618 }
619 
620 void
621 MacLow::ReceiveError (Ptr<Packet> packet, double rxSnr)
622 {
623  NS_LOG_FUNCTION (this << packet << rxSnr);
624  NS_LOG_DEBUG ("rx failed");
625  if (IsCfPeriod () && m_currentHdr.IsCfPoll ())
626  {
627  NS_ASSERT (m_currentTxop != 0);
629  }
630  else if (m_cfAckInfo.expectCfAck)
631  {
632  NS_ASSERT (m_currentTxop != 0);
633  Ptr<Txop> txop = m_currentTxop;
634  m_currentTxop = 0;
635  txop->MissedAck ();
636  }
637  m_cfAckInfo.expectCfAck = false;
638  return;
639 }
640 
641 void
643 {
644  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
646  CancelAllEvents ();
648  {
650  }
653  m_currentPacket = 0;
654  m_currentTxop = 0;
655 }
656 
657 void
659 {
660  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
661  CancelAllEvents ();
663  {
665  }
668  m_currentPacket = 0;
669  m_currentTxop = 0;
670 }
671 
672 void
674 {
675  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
676  CancelAllEvents ();
678  {
680  }
683  m_currentPacket = 0;
684  m_currentTxop = 0;
685 }
686 
687 void
688 MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
689 {
690  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << txVector.GetPreambleType ());
691  /* A packet is received from the PHY.
692  * When we have handled this packet,
693  * we handle any packet present in the
694  * packet queue.
695  */
696  WifiMacHeader hdr;
697  packet->RemoveHeader (hdr);
698  m_lastReceivedHdr = hdr;
699 
700  bool isPrevNavZero = IsNavZero ();
701  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
702  NotifyNav (packet, hdr);
703  if (hdr.IsRts ())
704  {
705  /* see section 9.2.5.7 802.11-1999
706  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
707  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
708  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
709  * that STA shall not respond to the RTS frame.
710  */
711  if (ampduSubframe)
712  {
713  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
714  }
715  else
716  {
717  if (isPrevNavZero
718  && hdr.GetAddr1 () == m_self)
719  {
720  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
722  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
723  rxSnr, txVector.GetMode ());
726  hdr.GetAddr2 (),
727  hdr.GetDuration (),
728  txVector,
729  rxSnr);
730  }
731  else
732  {
733  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
734  }
735  }
736  }
737  else if (hdr.IsCts ()
738  && hdr.GetAddr1 () == m_self
740  && m_currentPacket != 0)
741  {
742  if (ampduSubframe)
743  {
744  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
745  }
746 
747  NS_LOG_DEBUG ("received cts from=" << m_currentHdr.GetAddr1 ());
748 
749  SnrTag tag;
750  packet->RemovePacketTag (tag);
752  rxSnr, txVector.GetMode ());
754  rxSnr, txVector.GetMode (), tag.Get ());
755 
761  hdr.GetDuration ());
762  }
763  else if (hdr.IsAck ()
764  && hdr.GetAddr1 () == m_self
767  {
768  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
769  SnrTag tag;
770  packet->RemovePacketTag (tag);
771  //When fragmentation is used, only update manager when the last fragment is acknowledged
772  if (!m_txParams.HasNextPacket ())
773  {
775  rxSnr, txVector.GetMode ());
777  rxSnr, txVector.GetMode (), tag.Get ());
778  }
779  bool gotAck = false;
782  {
785  gotAck = true;
786  }
787  if (gotAck)
788  {
789  m_currentTxop->GotAck ();
790  }
792  {
794  {
796  }
797  else
798  {
800  }
801  }
802  else if (m_currentHdr.IsQosData () && m_currentTxop->HasTxop ())
803  {
805  {
807  }
808  else
809  {
811  }
812  }
813  m_ampdu = false;
814  if (m_currentHdr.IsQosData ())
815  {
817  }
818  }
819  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
822  {
823  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
824  SnrTag tag;
825  packet->RemovePacketTag (tag);
826  FlushAggregateQueue (GetTid (packet, hdr));
827  CtrlBAckResponseHeader blockAck;
828  packet->RemoveHeader (blockAck);
831  m_currentTxop->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
832  m_ampdu = false;
834  {
836  {
838  }
839  else
840  {
842  }
843  }
844  }
845  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
846  {
847  CtrlBAckRequestHeader blockAckReq;
848  packet->RemoveHeader (blockAckReq);
849  if (!blockAckReq.IsMultiTid ())
850  {
851  uint8_t tid = blockAckReq.GetTidInfo ();
852  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
853  if (it != m_bAckAgreements.end ())
854  {
855  //Update block ack cache
856  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
857  NS_ASSERT (i != m_bAckCaches.end ());
858  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
859 
860  //NS_ASSERT (m_sendAckEvent.IsExpired ());
862  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
863  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
864  if ((*it).second.first.IsImmediateBlockAck ())
865  {
866  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
869  blockAckReq,
870  hdr.GetAddr2 (),
871  hdr.GetDuration (),
872  txVector.GetMode (),
873  rxSnr);
874  }
875  else
876  {
877  NS_FATAL_ERROR ("Delayed block ack not supported.");
878  }
879  }
880  else
881  {
882  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
883  }
884  }
885  else
886  {
887  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
888  }
889  }
890  else if (hdr.IsCtl ())
891  {
892  if (hdr.IsCfEnd ())
893  {
894  NS_LOG_DEBUG ("rx CF-END ");
895  m_cfpStart = NanoSeconds (0);
897  {
898  NS_ASSERT (m_currentTxop != 0);
899  if (hdr.IsCfAck ())
900  {
901  m_currentTxop->GotAck ();
902  }
903  else
904  {
906  }
907  }
908  if (m_currentTxop != 0)
909  {
911  }
912  m_cfAckInfo.expectCfAck = false;
913  }
914  else
915  {
916  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
917  }
918  }
919  else if (hdr.GetAddr1 () == m_self)
920  {
921  if (hdr.IsCfPoll ())
922  {
924  if (m_cfAckInfo.expectCfAck && !hdr.IsCfAck ())
925  {
926  NS_ASSERT (m_currentTxop != 0);
927  Ptr<Txop> txop = m_currentTxop;
928  m_currentTxop = 0;
929  txop->MissedAck ();
930  m_cfAckInfo.expectCfAck = false;
931  }
932  }
933  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
934  rxSnr, txVector.GetMode ());
935  if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
936  {
937  /* From section 9.10.4 in IEEE 802.11:
938  Upon the receipt of a QoS data frame from the originator for which
939  the Block Ack agreement exists, the recipient shall buffer the MSDU
940  regardless of the value of the Ack Policy subfield within the
941  QoS Control field of the QoS data frame. */
942  if (hdr.IsQosAck () && !ampduSubframe)
943  {
944  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
945  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
946 
947  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
948  hdr.GetAddr2 (), hdr.GetQosTid ());
949  RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
953  hdr.GetAddr2 (),
954  hdr.GetDuration (),
955  txVector.GetMode (),
956  rxSnr);
957  }
958  else if (hdr.IsQosBlockAck ())
959  {
960  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
961  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
962  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
963  }
964  return;
965  }
966  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
967  {
968  /* This happens if a packet with ack policy Block Ack is received and a block ack
969  agreement for that packet doesn't exist.
970 
971  From section 11.5.3 in IEEE 802.11e:
972  When a recipient does not have an active Block ack for a TID, but receives
973  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
974  them and shall send a DELBA frame using the normal access
975  mechanisms. */
976  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
977  m_edca[ac]->SendDelbaFrame (hdr.GetAddr2 (), hdr.GetQosTid (), false);
978  return;
979  }
980  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
981  {
982  if (ampduSubframe)
983  {
984  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
985  }
986  else
987  {
988  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
989  }
990  }
991  else if (hdr.IsData () || hdr.IsMgt ())
992  {
993  if (hdr.IsProbeResp ())
994  {
995  // Apply SNR tag for probe response quality measurements
996  SnrTag tag;
997  tag.Set (rxSnr);
998  packet->AddPacketTag (tag);
999  }
1000  if (hdr.IsMgt () && ampduSubframe)
1001  {
1002  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1003  }
1004  else
1005  {
1006  if (IsCfPeriod ())
1007  {
1008  if (hdr.HasData ())
1009  {
1010  m_cfAckInfo.appendCfAck = true;
1011  m_cfAckInfo.address = hdr.GetAddr2 ();
1012  }
1013  }
1014  else
1015  {
1016  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1019  &MacLow::SendAckAfterData, this,
1020  hdr.GetAddr2 (),
1021  hdr.GetDuration (),
1022  txVector.GetMode (),
1023  rxSnr);
1024  }
1025  }
1026  }
1027  goto rxPacket;
1028  }
1029  else if (hdr.GetAddr1 ().IsGroup ())
1030  {
1031  if (ampduSubframe)
1032  {
1033  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1034  }
1035  else
1036  {
1037  if (hdr.IsData () || hdr.IsMgt ())
1038  {
1039  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1040  if (hdr.IsBeacon ())
1041  {
1042  // Apply SNR tag for beacon quality measurements
1043  SnrTag tag;
1044  tag.Set (rxSnr);
1045  packet->AddPacketTag (tag);
1046  }
1047  goto rxPacket;
1048  }
1049  }
1050  }
1051  else if (m_promisc)
1052  {
1053  NS_ASSERT (hdr.GetAddr1 () != m_self);
1054  if (hdr.IsData ())
1055  {
1056  goto rxPacket;
1057  }
1058  }
1059  else
1060  {
1061  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1062  {
1063  m_cfAckInfo.expectCfAck = false;
1064  NS_ASSERT (m_currentTxop != 0);
1065  m_currentTxop->GotAck ();
1066  }
1067  NS_LOG_DEBUG ("rx not for me from=" << hdr.GetAddr2 ());
1068  }
1069  return;
1070 rxPacket:
1071  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1072  {
1073  m_cfAckInfo.expectCfAck = false;
1074  NS_ASSERT (m_currentTxop != 0);
1075  m_currentTxop->GotAck ();
1076  }
1077  WifiMacTrailer fcs;
1078  packet->RemoveTrailer (fcs);
1079  m_rxCallback (packet, &hdr);
1080  return;
1081 }
1082 
1083 uint32_t
1085 {
1086  WifiMacHeader cfEnd;
1088  {
1089  cfEnd.SetType (WIFI_MAC_CTL_END_ACK);
1090  }
1091  else
1092  {
1093  cfEnd.SetType (WIFI_MAC_CTL_END);
1094  }
1095  return cfEnd.GetSize () + 4;
1096 }
1097 
1098 Time
1100 {
1101  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1102  return GetAckDuration (ackTxVector);
1103 }
1104 
1105 Time
1107 {
1108  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1109  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetFrequency ());
1110 }
1111 
1112 Time
1113 MacLow::GetBlockAckDuration (WifiTxVector blockAckReqTxVector, BlockAckType type) const
1114 {
1115  /*
1116  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1117  * as the BlockAckReq.
1118  */
1119  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1120 }
1121 
1122 Time
1124 {
1125  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1126  return GetCtsDuration (ctsTxVector);
1127 }
1128 
1129 Time
1131 {
1132  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1133  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1134 }
1135 
1138 {
1139  Mac48Address to = hdr->GetAddr1 ();
1140  return m_stationManager->GetRtsTxVector (to, hdr, packet);
1141 }
1142 
1145 {
1146  Mac48Address to = hdr->GetAddr1 ();
1147  return m_stationManager->GetDataTxVector (to, hdr, packet);
1148 }
1149 
1152 {
1153  return m_stationManager->GetCtsTxVector (to, rtsTxMode);
1154 }
1155 
1158 {
1159  return m_stationManager->GetAckTxVector (to, dataTxMode);
1160 }
1161 
1164 {
1165  return m_stationManager->GetBlockAckTxVector (to, dataTxMode);
1166 }
1167 
1170 {
1171  return GetCtsTxVector (to, rtsTxMode);
1172 }
1173 
1176 {
1177  return GetAckTxVector (to, dataTxMode);
1178 }
1179 
1180 Time
1182  const WifiMacHeader* hdr,
1183  const MacLowTransmissionParameters& params,
1184  uint32_t fragmentSize) const
1185 {
1186  Time txTime = Seconds (0);
1187  if (params.MustSendRts ())
1188  {
1189  WifiTxVector rtsTxVector = GetRtsTxVector (packet, hdr);
1190  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1191  txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
1192  txTime += Time (GetSifs () * 2);
1193  }
1194  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1195  uint32_t dataSize;
1196  if (fragmentSize > 0)
1197  {
1198  Ptr<const Packet> fragment = Create<Packet> (fragmentSize);
1199  dataSize = GetSize (fragment, hdr, m_ampdu);
1200  }
1201  else
1202  {
1203  dataSize = GetSize (packet, hdr, m_ampdu);
1204  }
1205  txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, m_phy->GetFrequency ());
1206  txTime += GetSifs ();
1207  if (params.MustWaitNormalAck ())
1208  {
1209  txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
1210  }
1211  return txTime;
1212 }
1213 
1214 Time
1216  const WifiMacHeader* hdr,
1217  const MacLowTransmissionParameters& params) const
1218 {
1219  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1220  if (params.HasNextPacket ())
1221  {
1222  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1223  txTime += GetSifs ();
1224  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, m_phy->GetFrequency ());
1225  }
1226  return txTime;
1227 }
1228 
1229 void
1231 {
1233  if (hdr.GetRawDuration () > 32767)
1234  {
1235  //All stations process Duration field values less than or equal to 32 767 from valid data frames
1236  //to update their NAV settings as appropriate under the coordination function rules.
1237  return;
1238  }
1239  if (hdr.IsCfEnd () && hdr.GetAddr2 () == m_bssid)
1240  {
1241  //see section 9.3.2.2 802.11-1999
1242  DoNavResetNow (Seconds (0));
1243  return;
1244  }
1245  else if (hdr.GetAddr1 () != m_self)
1246  {
1247  // see section 9.2.5.4 802.11-1999
1248  Time duration = hdr.GetDuration ();
1249  bool navUpdated = DoNavStartNow (duration);
1250  if (hdr.IsRts () && navUpdated)
1251  {
1260  WifiMacHeader cts;
1261  cts.SetType (WIFI_MAC_CTL_CTS);
1262  WifiTxVector txVector = GetRtsTxVector (packet, &hdr);
1263  Time navCounterResetCtsMissedDelay =
1264  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetFrequency ()) +
1265  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1266  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1268  Simulator::Now ());
1269  }
1270  }
1271 }
1272 
1273 void
1275 {
1276  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1277  {
1278  DoNavResetNow (Seconds (0));
1279  }
1280 }
1281 
1282 void
1284 {
1285  NS_LOG_FUNCTION (this << duration);
1286  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1287  {
1288  (*i)->NotifyNavResetNow (duration);
1289  }
1291  m_lastNavDuration = duration;
1292 }
1293 
1294 bool
1296 {
1297  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1298  {
1299  (*i)->NotifyNavStartNow (duration);
1300  }
1301  Time newNavEnd = Simulator::Now () + duration;
1302  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1303  if (newNavEnd > oldNavEnd)
1304  {
1306  m_lastNavDuration = duration;
1307  return true;
1308  }
1309  return false;
1310 }
1311 
1312 void
1314 {
1315  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1316  {
1317  (*i)->NotifyAckTimeoutStartNow (duration);
1318  }
1319 }
1320 
1321 void
1323 {
1324  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1325  {
1326  (*i)->NotifyAckTimeoutResetNow ();
1327  }
1328 }
1329 
1330 void
1332 {
1333  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1334  {
1335  (*i)->NotifyCtsTimeoutStartNow (duration);
1336  }
1337 }
1338 
1339 void
1341 {
1342  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1343  {
1344  (*i)->NotifyCtsTimeoutResetNow ();
1345  }
1346 }
1347 
1348 void
1350 {
1351  NS_LOG_FUNCTION (this << packet << hdr << txVector);
1352  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
1353  ", to=" << hdr->GetAddr1 () <<
1354  ", size=" << packet->GetSize () <<
1355  ", mode=" << txVector.GetMode () <<
1356  ", preamble=" << txVector.GetPreambleType () <<
1357  ", duration=" << hdr->GetDuration () <<
1358  ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
1359  if (!m_ampdu || hdr->IsAck () || hdr->IsRts () || hdr->IsCts () || hdr->IsBlockAck () || hdr->IsMgt ())
1360  {
1361  if (hdr->IsCfPoll () && m_stationManager->HasPcfSupported ())
1362  {
1364  }
1365  if (hdr->IsBeacon () && m_stationManager->HasPcfSupported ())
1366  {
1368  {
1370  }
1372  }
1373  else if (hdr->IsCfEnd () && m_stationManager->HasPcfSupported ())
1374  {
1375  m_cfpStart = NanoSeconds (0);
1377  m_cfAckInfo.appendCfAck = false;
1378  m_cfAckInfo.expectCfAck = false;
1379  }
1380  else if (IsCfPeriod () && hdr->HasData ())
1381  {
1382  m_cfAckInfo.expectCfAck = true;
1383  }
1384  m_phy->SendPacket (packet, txVector);
1385  }
1386  else
1387  {
1388  Ptr<Packet> newPacket;
1389  Ptr <WifiMacQueueItem> dequeuedItem;
1390  WifiMacHeader newHdr;
1391  uint32_t queueSize = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
1392  bool singleMpdu = false;
1393  bool last = false;
1394  MpduType mpdutype = NORMAL_MPDU;
1395 
1396  uint8_t tid = GetTid (packet, *hdr);
1397  AcIndex ac = QosUtilsMapTidToAc (tid);
1398  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
1399 
1400  if (queueSize == 1)
1401  {
1402  singleMpdu = true;
1403  }
1404 
1405  //Add packet tag
1406  AmpduTag ampdutag;
1407  Time delay = Seconds (0);
1408  Time remainingAmpduDuration = m_phy->CalculateTxDuration (packet->GetSize (), txVector, m_phy->GetFrequency ());
1409  if (queueSize > 1 || singleMpdu)
1410  {
1411  txVector.SetAggregation (true);
1412  }
1413  for (; queueSize > 0; queueSize--)
1414  {
1415  dequeuedItem = m_aggregateQueue[GetTid (packet, *hdr)]->Dequeue ();
1416  newHdr = dequeuedItem->GetHeader ();
1417  newPacket = dequeuedItem->GetPacket ()->Copy ();
1418  newHdr.SetDuration (hdr->GetDuration ());
1419  newPacket->AddHeader (newHdr);
1420  AddWifiMacTrailer (newPacket);
1421  if (queueSize == 1)
1422  {
1423  last = true;
1424  mpdutype = LAST_MPDU_IN_AGGREGATE;
1425  }
1426 
1427  edcaIt->second->GetMpduAggregator ()->AddHeaderAndPad (newPacket, last, singleMpdu);
1428 
1429  if (delay.IsZero ())
1430  {
1431  if (!singleMpdu)
1432  {
1433  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1434  mpdutype = MPDU_IN_AGGREGATE;
1435  }
1436  else
1437  {
1438  NS_LOG_DEBUG ("Sending S-MPDU");
1439  mpdutype = NORMAL_MPDU;
1440  }
1441  }
1442 
1443  Time mpduDuration = m_phy->CalculateTxDuration (newPacket->GetSize (), txVector, m_phy->GetFrequency (), mpdutype, 0);
1444  remainingAmpduDuration -= mpduDuration;
1445 
1446  ampdutag.SetRemainingNbOfMpdus (static_cast<uint8_t> (queueSize - 1));
1447  if (queueSize > 1)
1448  {
1449  ampdutag.SetRemainingAmpduDuration (remainingAmpduDuration);
1450  }
1451  else
1452  {
1453  ampdutag.SetRemainingAmpduDuration (NanoSeconds (0));
1454  }
1455  newPacket->AddPacketTag (ampdutag);
1456 
1457  if (delay.IsZero ())
1458  {
1459  m_phy->SendPacket (newPacket, txVector, mpdutype);
1460  }
1461  else
1462  {
1463  Simulator::Schedule (delay, &MacLow::SendMpdu, this, newPacket, txVector, mpdutype);
1464  }
1465  if (queueSize > 1)
1466  {
1467  NS_ASSERT (remainingAmpduDuration > 0);
1468  delay = delay + mpduDuration;
1469  }
1470 
1472  }
1473  }
1474 }
1475 
1476 void
1478 {
1479  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1480  m_phy->SendPacket (packet, txVector, mpdutype);
1481 }
1482 
1483 void
1485 {
1486  NS_LOG_FUNCTION (this);
1487  //to be reworked
1488  bool busy = false;
1489  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1490  {
1491  busy = (*i)->IsBusy ();
1492  }
1493  if (!busy)
1494  {
1495  NS_ASSERT (m_currentTxop != 0);
1497  m_cfAckInfo.expectCfAck = false;
1498  }
1499 }
1500 
1501 void
1503 {
1504  NS_LOG_FUNCTION (this);
1505  NS_LOG_DEBUG ("cts timeout");
1510  Ptr<Txop> txop = m_currentTxop;
1511  m_currentTxop = 0;
1512  m_ampdu = false;
1513  txop->MissedCts ();
1514 }
1515 
1516 void
1518 {
1519  NS_LOG_FUNCTION (this);
1520  NS_LOG_DEBUG ("normal ack timeout");
1525  Ptr<Txop> txop = m_currentTxop;
1526  m_currentTxop = 0;
1527  m_ampdu = false;
1528  if (m_currentHdr.IsQosData ())
1529  {
1531  }
1532  txop->MissedAck ();
1533 }
1534 
1535 void
1537 {
1538  NS_LOG_FUNCTION (this);
1539  NS_LOG_DEBUG ("block ack timeout");
1540  Ptr<Txop> txop = m_currentTxop;
1541  m_currentTxop = 0;
1542  m_ampdu = false;
1543  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1544  AmpduTag ampdu;
1546  txop->MissedBlockAck (ampdu.GetRemainingNbOfMpdus() + 1);
1547  FlushAggregateQueue (tid);
1548 }
1549 
1550 void
1552 {
1553  NS_LOG_FUNCTION (this);
1554  /* send an RTS for this packet. */
1555  WifiMacHeader rts;
1556  rts.SetType (WIFI_MAC_CTL_RTS);
1557  rts.SetDsNotFrom ();
1558  rts.SetDsNotTo ();
1559  rts.SetNoRetry ();
1560  rts.SetNoMoreFragments ();
1561  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1562  rts.SetAddr2 (m_self);
1564  Time duration = Seconds (0);
1565 
1566  duration += GetSifs ();
1567  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1568  duration += GetSifs ();
1571  duration += GetSifs ();
1573  {
1575  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1576  }
1578  {
1580  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1581  }
1582  else if (m_txParams.MustWaitNormalAck ())
1583  {
1585  }
1586  if (m_txParams.HasNextPacket ())
1587  {
1591  {
1592  duration += GetSifs ();
1594  }
1595  }
1596  rts.SetDuration (duration);
1597 
1598  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1599  Time timerDelay = txDuration + GetCtsTimeout ();
1600 
1602  NotifyCtsTimeoutStartNow (timerDelay);
1604 
1605  Ptr<Packet> packet = Create<Packet> ();
1606  packet->AddHeader (rts);
1607  AddWifiMacTrailer (packet);
1608 
1609  ForwardDown (packet, &rts, rtsTxVector);
1610 }
1611 
1612 void
1614 {
1616  if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
1617  {
1618  Time timerDelay = txDuration + GetAckTimeout ();
1620  NotifyAckTimeoutStartNow (timerDelay);
1622  }
1623  else if (m_txParams.MustWaitBasicBlockAck ())
1624  {
1625  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1627  NotifyAckTimeoutStartNow (timerDelay);
1629  }
1631  {
1632  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1634  NotifyAckTimeoutStartNow (timerDelay);
1636  }
1637  else if (m_txParams.HasNextPacket ())
1638  {
1640  Time delay = txDuration;
1642  {
1643  delay += GetRifs ();
1644  }
1645  else
1646  {
1647  delay += GetSifs ();
1648  }
1650  }
1652  {
1653  Time delay = txDuration;
1655  {
1656  delay += GetRifs ();
1657  }
1658  else
1659  {
1660  delay += GetSifs ();
1661  }
1663  }
1664  else
1665  {
1666  // since we do not expect any timer to be triggered.
1668  }
1669 }
1670 
1671 void
1673 {
1674  NS_LOG_FUNCTION (this);
1675  /* send this packet directly. No RTS is needed. */
1677 
1678  if (!IsCfPeriod ())
1679  {
1680  Time duration = Seconds (0);
1682  {
1683  duration += GetSifs ();
1685  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1686  }
1688  {
1689  duration += GetSifs ();
1691  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1692  }
1693  else if (m_txParams.MustWaitNormalAck ())
1694  {
1695  duration += GetSifs ();
1697  }
1698  if (m_txParams.HasNextPacket ())
1699  {
1701  {
1702  duration += GetRifs ();
1703  }
1704  else
1705  {
1706  duration += GetSifs ();
1707  }
1711  {
1712  duration += GetSifs ();
1714  }
1715  }
1716  m_currentHdr.SetDuration (duration);
1717  }
1718  else
1719  {
1720  if (m_currentHdr.IsCfEnd ())
1721  {
1723  }
1724  else
1725  {
1726  m_currentHdr.SetRawDuration (32768);
1727  }
1728  }
1729 
1730  Ptr <Packet> packet = m_currentPacket->Copy ();
1731  if (m_ampdu)
1732  {
1734  }
1735  else
1736  {
1738  {
1739  switch (m_currentHdr.GetType ())
1740  {
1741  case WIFI_MAC_DATA:
1743  break;
1744  case WIFI_MAC_DATA_CFPOLL:
1746  break;
1747  case WIFI_MAC_DATA_NULL:
1749  break;
1752  break;
1753  case WIFI_MAC_CTL_END:
1755  break;
1756  default:
1757  NS_ASSERT (false);
1758  break;
1759  }
1761  //Standard says that, for frames of type Data+CF-ACK, Data+CF-Poll+CF-ACK, and CF-Poll+CF-ACK,
1762  //the rate chosen to transmit the frame must be supported by both the addressed recipient STA and the STA to which the ACK is intended.
1763  //This ideally requires the rate manager to handle this case, but this requires to update all rate manager classes.
1764  //Instead, we simply fetch two TxVector and we select the one with the lowest datarate.
1765  //This should be later changed, at the latest once HCCA is implemented for HT/VHT stations.
1766  WifiMacHeader tmpHdr = m_currentHdr;
1767  tmpHdr.SetAddr1 (m_cfAckInfo.address);
1768  WifiTxVector tmpTxVector = GetDataTxVector (packet, &tmpHdr);
1769  if (tmpTxVector.GetMode ().GetDataRate (tmpTxVector) < m_currentTxVector.GetMode ().GetDataRate (m_currentTxVector))
1770  {
1771  m_currentTxVector = tmpTxVector;
1772  }
1773  m_cfAckInfo.appendCfAck = false;
1775  }
1776  packet->AddHeader (m_currentHdr);
1777  AddWifiMacTrailer (packet);
1778  }
1780 }
1781 
1782 bool
1783 MacLow::IsNavZero (void) const
1784 {
1786 }
1787 
1788 void
1790 {
1791  WifiMacHeader cts;
1792  cts.SetType (WIFI_MAC_CTL_CTS);
1793  cts.SetDsNotFrom ();
1794  cts.SetDsNotTo ();
1795  cts.SetNoMoreFragments ();
1796  cts.SetNoRetry ();
1797  cts.SetAddr1 (m_self);
1798 
1800  Time duration = Seconds (0);
1801 
1802  duration += GetSifs ();
1806  {
1807  duration += GetSifs ();
1809  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1810  }
1812  {
1813  duration += GetSifs ();
1815  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1816  }
1817  else if (m_txParams.MustWaitNormalAck ())
1818  {
1819  duration += GetSifs ();
1821  }
1822  if (m_txParams.HasNextPacket ())
1823  {
1824  duration += GetSifs ();
1828  {
1829  duration += GetSifs ();
1831  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1832  }
1833  else if (m_txParams.MustWaitNormalAck ())
1834  {
1835  duration += GetSifs ();
1837  }
1838  }
1839 
1840  cts.SetDuration (duration);
1841 
1842  Ptr<Packet> packet = Create<Packet> ();
1843  packet->AddHeader (cts);
1844  AddWifiMacTrailer (packet);
1845 
1846  ForwardDown (packet, &cts, ctsTxVector);
1847 
1848  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1849  txDuration += GetSifs ();
1851 
1852  m_sendDataEvent = Simulator::Schedule (txDuration,
1853  &MacLow::SendDataAfterCts, this,
1854  duration);
1855 }
1856 
1857 void
1858 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
1859 {
1860  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
1861  /* send a CTS when you receive a RTS
1862  * right after SIFS.
1863  */
1864  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
1865  WifiMacHeader cts;
1866  cts.SetType (WIFI_MAC_CTL_CTS);
1867  cts.SetDsNotFrom ();
1868  cts.SetDsNotTo ();
1869  cts.SetNoMoreFragments ();
1870  cts.SetNoRetry ();
1871  cts.SetAddr1 (source);
1872  duration -= GetCtsDuration (source, rtsTxVector);
1873  duration -= GetSifs ();
1874  NS_ASSERT (duration.IsPositive ());
1875  cts.SetDuration (duration);
1876 
1877  Ptr<Packet> packet = Create<Packet> ();
1878  packet->AddHeader (cts);
1879  AddWifiMacTrailer (packet);
1880 
1881  SnrTag tag;
1882  tag.Set (rtsSnr);
1883  packet->AddPacketTag (tag);
1884 
1885  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1886  ForwardDown (packet, &cts, ctsTxVector);
1887 }
1888 
1889 void
1891 {
1892  NS_LOG_FUNCTION (this);
1893  /* send the third step in a
1894  * RTS/CTS/DATA/ACK handshake
1895  */
1896  NS_ASSERT (m_currentPacket != 0);
1897 
1898  if (m_currentHdr.IsQosData ())
1899  {
1900  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1901  if (!m_aggregateQueue[GetTid (m_currentPacket, m_currentHdr)]->IsEmpty ())
1902  {
1903  for (std::vector<Item>::size_type i = 0; i != m_txPackets[tid].size (); i++)
1904  {
1905  AcIndex ac = QosUtilsMapTidToAc (tid);
1906  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
1907  edcaIt->second->CompleteMpduTx (m_txPackets[tid].at (i).packet, m_txPackets[tid].at (i).hdr, m_txPackets[tid].at (i).timestamp);
1908  }
1909  }
1910  }
1911 
1913  Time newDuration = Seconds (0);
1915  {
1916  newDuration += GetSifs ();
1918  newDuration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1919  }
1921  {
1922  newDuration += GetSifs ();
1924  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1925  }
1926  else if (m_txParams.MustWaitNormalAck ())
1927  {
1928  newDuration += GetSifs ();
1930  }
1931  if (m_txParams.HasNextPacket ())
1932  {
1934  {
1935  newDuration += GetRifs ();
1936  }
1937  else
1938  {
1939  newDuration += GetSifs ();
1940  }
1943  {
1944  newDuration += GetSifs ();
1946  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1947  }
1948  else if (m_txParams.MustWaitNormalAck ())
1949  {
1950  newDuration += GetSifs ();
1952  }
1953  }
1954 
1956  duration -= txDuration;
1957  duration -= GetSifs ();
1958 
1959  duration = std::max (duration, newDuration);
1960  NS_ASSERT (duration.IsPositive ());
1961  m_currentHdr.SetDuration (duration);
1962  Ptr <Packet> packet = m_currentPacket->Copy ();
1963  if (m_ampdu)
1964  {
1966  }
1967  else
1968  {
1969  packet->AddHeader (m_currentHdr);
1970  AddWifiMacTrailer (packet);
1971  }
1973 }
1974 
1975 void
1977 {
1978  NS_LOG_FUNCTION (this);
1980 }
1981 
1982 void
1984 {
1985  NS_LOG_FUNCTION (this);
1987 }
1988 
1989 void
1991 {
1992  NS_LOG_FUNCTION (this);
1994  {
1996  }
1997  if (!m_cfAckInfo.expectCfAck)
1998  {
1999  Ptr<Txop> txop = m_currentTxop;
2000  txop->EndTxNoAck ();
2001  }
2002  if (!IsCfPeriod ())
2003  {
2004  m_currentTxop = 0;
2005  }
2006 }
2007 
2008 void
2009 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2010 {
2011  NS_LOG_FUNCTION (this);
2012  // send an ACK, after SIFS, when you receive a packet
2013  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2014  WifiMacHeader ack;
2015  ack.SetType (WIFI_MAC_CTL_ACK);
2016  ack.SetDsNotFrom ();
2017  ack.SetDsNotTo ();
2018  ack.SetNoRetry ();
2019  ack.SetNoMoreFragments ();
2020  ack.SetAddr1 (source);
2021  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2022  // minus the time to transmit the ACK frame and its SIFS interval
2023  duration -= GetAckDuration (ackTxVector);
2024  duration -= GetSifs ();
2025  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
2026  ack.SetDuration (duration);
2027 
2028  Ptr<Packet> packet = Create<Packet> ();
2029  packet->AddHeader (ack);
2030  AddWifiMacTrailer (packet);
2031 
2032  SnrTag tag;
2033  tag.Set (dataSnr);
2034  packet->AddPacketTag (tag);
2035 
2036  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2037  ForwardDown (packet, &ack, ackTxVector);
2038 }
2039 
2040 bool
2042 {
2046  {
2047  Mac48Address originator = hdr.GetAddr2 ();
2048  uint8_t tid = 0;
2049  if (hdr.IsQosData ())
2050  {
2051  tid = hdr.GetQosTid ();
2052  }
2053  uint16_t seqNumber = hdr.GetSequenceNumber ();
2054  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2055  if (it != m_bAckAgreements.end ())
2056  {
2057  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2058  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2059  {
2060  StoreMpduIfNeeded (packet, hdr);
2061  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2062  {
2063  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2064  if (delta > 1)
2065  {
2066  (*it).second.first.SetWinEnd (seqNumber);
2067  int16_t winEnd = (*it).second.first.GetWinEnd ();
2068  int16_t bufferSize = (*it).second.first.GetBufferSize ();
2069  uint16_t sum = (static_cast<uint16_t> (std::abs (winEnd - bufferSize + 1))) % 4096;
2070  (*it).second.first.SetStartingSequence (sum);
2071  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2072  }
2073  }
2074  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2075  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2076  }
2077  return true;
2078  }
2079  return false;
2080  }
2081  return StoreMpduIfNeeded (packet, hdr);
2082 }
2083 
2084 bool
2086 {
2087  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2088  if (it != m_bAckAgreements.end ())
2089  {
2090  WifiMacTrailer fcs;
2091  packet->RemoveTrailer (fcs);
2092  BufferedPacket bufferedPacket (packet, hdr);
2093 
2094  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2095  uint32_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2096 
2097  BufferedPacketI i = (*it).second.second.begin ();
2098  for (; i != (*it).second.second.end ()
2099  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2100  {
2101  }
2102  (*it).second.second.insert (i, bufferedPacket);
2103 
2104  //Update block ack cache
2105  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2106  NS_ASSERT (j != m_bAckCaches.end ());
2107  (*j).second.UpdateWithMpdu (&hdr);
2108  return true;
2109  }
2110  return false;
2111 }
2112 
2113 void
2115  uint16_t startingSeq)
2116 {
2117  NS_LOG_FUNCTION (this);
2118  uint8_t tid = respHdr->GetTid ();
2119  BlockAckAgreement agreement (originator, tid);
2120  if (respHdr->IsImmediateBlockAck ())
2121  {
2122  agreement.SetImmediateBlockAck ();
2123  }
2124  else
2125  {
2126  agreement.SetDelayedBlockAck ();
2127  }
2128  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2129  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2130  agreement.SetTimeout (respHdr->GetTimeout ());
2131  agreement.SetStartingSequence (startingSeq);
2132 
2133  std::list<BufferedPacket> buffer (0);
2134  AgreementKey key (originator, respHdr->GetTid ());
2135  AgreementValue value (agreement, buffer);
2136  m_bAckAgreements.insert (std::make_pair (key, value));
2137 
2138  BlockAckCache cache;
2139  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2140  m_bAckCaches.insert (std::make_pair (key, cache));
2141 
2142  if (respHdr->GetTimeout () != 0)
2143  {
2144  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2145  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2146 
2147  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2148 
2149  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2151  m_edca[ac], originator, tid, false);
2152  }
2153 }
2154 
2155 void
2157 {
2158  NS_LOG_FUNCTION (this);
2159  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2160  if (it != m_bAckAgreements.end ())
2161  {
2162  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2163  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2164  m_bAckAgreements.erase (it);
2165  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2166  NS_ASSERT (i != m_bAckCaches.end ());
2167  m_bAckCaches.erase (i);
2168  }
2169 }
2170 
2171 void
2173 {
2174  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2175  if (it != m_bAckAgreements.end ())
2176  {
2177  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2178  uint32_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2179  BufferedPacketI last = (*it).second.second.begin ();
2180  uint16_t guard = 0;
2181  if (last != (*it).second.second.end ())
2182  {
2183  guard = (*it).second.second.begin ()->second.GetSequenceControl ();
2184  }
2185  BufferedPacketI i = (*it).second.second.begin ();
2186  for (; i != (*it).second.second.end ()
2187  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedStart; )
2188  {
2189  if (guard == (*i).second.GetSequenceControl ())
2190  {
2191  if (!(*i).second.IsMoreFragments ())
2192  {
2193  while (last != i)
2194  {
2195  m_rxCallback ((*last).first, &(*last).second);
2196  last++;
2197  }
2198  m_rxCallback ((*last).first, &(*last).second);
2199  last++;
2200  /* go to next packet */
2201  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2202  {
2203  i++;
2204  }
2205  if (i != (*it).second.second.end ())
2206  {
2207  guard = (*i).second.GetSequenceControl ();
2208  last = i;
2209  }
2210  }
2211  else
2212  {
2213  guard++;
2214  }
2215  }
2216  else
2217  {
2218  /* go to next packet */
2219  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2220  {
2221  i++;
2222  }
2223  if (i != (*it).second.second.end ())
2224  {
2225  guard = (*i).second.GetSequenceControl ();
2226  last = i;
2227  }
2228  }
2229  }
2230  (*it).second.second.erase ((*it).second.second.begin (), i);
2231  }
2232 }
2233 
2234 void
2236 {
2237  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2238  if (it != m_bAckAgreements.end ())
2239  {
2240  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2241  BufferedPacketI lastComplete = (*it).second.second.begin ();
2242  BufferedPacketI i = (*it).second.second.begin ();
2243  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2244  {
2245  if (!(*i).second.IsMoreFragments ())
2246  {
2247  while (lastComplete != i)
2248  {
2249  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2250  lastComplete++;
2251  }
2252  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2253  lastComplete++;
2254  }
2255  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2256  }
2257  (*it).second.first.SetStartingSequenceControl (guard);
2258  /* All packets already forwarded to WifiMac must be removed from buffer:
2259  [begin (), lastComplete) */
2260  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2261  }
2262 }
2263 void
2264 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2265  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2266 {
2267  NS_LOG_FUNCTION (this);
2268  Ptr<Packet> packet = Create<Packet> ();
2269  packet->AddHeader (*blockAck);
2270 
2271  WifiMacHeader hdr;
2273  hdr.SetAddr1 (originator);
2274  hdr.SetAddr2 (GetAddress ());
2275  hdr.SetDsNotFrom ();
2276  hdr.SetDsNotTo ();
2277  hdr.SetNoRetry ();
2278  hdr.SetNoMoreFragments ();
2279 
2280  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2281 
2282  if (immediate)
2283  {
2285  duration -= GetSifs ();
2286  if (blockAck->IsBasic ())
2287  {
2288  duration -= GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
2289  }
2290  else if (blockAck->IsCompressed ())
2291  {
2292  duration -= GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2293  }
2294  else if (blockAck->IsMultiTid ())
2295  {
2296  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2297  }
2298  }
2299  else
2300  {
2301  m_txParams.EnableAck ();
2302  duration += GetSifs ();
2303  duration += GetAckDuration (originator, blockAckReqTxVector);
2304  }
2306 
2307  if (!immediate)
2308  {
2309  StartDataTxTimers (blockAckReqTxVector);
2310  }
2311 
2312  NS_ASSERT (duration.IsPositive ());
2313  hdr.SetDuration (duration);
2314  //here should be present a control about immediate or delayed block ack
2315  //for now we assume immediate
2316  packet->AddHeader (hdr);
2317  AddWifiMacTrailer (packet);
2318  SnrTag tag;
2319  tag.Set (rxSnr);
2320  packet->AddPacketTag (tag);
2321  ForwardDown (packet, &hdr, blockAckReqTxVector);
2322 }
2323 
2324 void
2325 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2326 {
2327  NS_LOG_FUNCTION (this);
2328  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2329  {
2330  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2331  CtrlBAckResponseHeader blockAck;
2332  uint16_t seqNumber = 0;
2333  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2334  NS_ASSERT (i != m_bAckCaches.end ());
2335  seqNumber = (*i).second.GetWinStart ();
2336 
2337  bool immediate = true;
2338  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2339  blockAck.SetStartingSequence (seqNumber);
2340  blockAck.SetTidInfo (tid);
2341  immediate = (*it).second.first.IsImmediateBlockAck ();
2342  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2343  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2344  (*i).second.FillBlockAckBitmap (&blockAck);
2345 
2346  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode (), rxSnr);
2347  }
2348  else
2349  {
2350  NS_LOG_DEBUG ("Skip block ack response!");
2351  }
2352 }
2353 
2354 void
2356  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2357 {
2358  NS_LOG_FUNCTION (this);
2359  CtrlBAckResponseHeader blockAck;
2360  uint8_t tid = 0;
2361  bool immediate = false;
2362  if (!reqHdr.IsMultiTid ())
2363  {
2364  tid = reqHdr.GetTidInfo ();
2365  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2366  if (it != m_bAckAgreements.end ())
2367  {
2368  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2369  blockAck.SetTidInfo (tid);
2370  immediate = (*it).second.first.IsImmediateBlockAck ();
2371  if (reqHdr.IsBasic ())
2372  {
2373  blockAck.SetType (BASIC_BLOCK_ACK);
2374  }
2375  else if (reqHdr.IsCompressed ())
2376  {
2377  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2378  }
2379  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2380  NS_ASSERT (i != m_bAckCaches.end ());
2381  (*i).second.FillBlockAckBitmap (&blockAck);
2382  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2383 
2387  {
2388  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2389  * See 9.10.3 in IEEE 802.11e standard.
2390  */
2392  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2393  }
2394  else
2395  {
2396  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2397  {
2398  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2399  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2401  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2402  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2403  }
2404  }
2405  }
2406  else
2407  {
2408  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2409  }
2410  }
2411  else
2412  {
2413  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2414  }
2415  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2416 }
2417 
2418 void
2420 {
2421  if (agreement.GetTimeout () != 0)
2422  {
2423  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2424  agreement.m_inactivityEvent.Cancel ();
2425  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2426  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2427  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
2429  m_edca[ac], agreement.GetPeer (),
2430  agreement.GetTid (), false);
2431  }
2432 }
2433 
2434 void
2436 {
2437  m_edca.insert (std::make_pair (ac, edca));
2438 }
2439 
2440 void
2441 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector)
2442 {
2443  NS_LOG_FUNCTION (this);
2444  AmpduTag ampdu;
2445  bool normalAck = false;
2446  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2447  if (aggregatedPacket->RemovePacketTag (ampdu))
2448  {
2449  ampduSubframe = true;
2451  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2452 
2453  WifiMacHeader firsthdr;
2454  (*n).first->PeekHeader (firsthdr);
2455  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2456  NotifyNav ((*n).first, firsthdr);
2457 
2458  if (firsthdr.GetAddr1 () == m_self)
2459  {
2460  bool singleMpdu = (*n).second.GetEof ();
2461  if (singleMpdu)
2462  {
2463  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2464  NS_LOG_DEBUG ("Receive S-MPDU");
2465  ampduSubframe = false;
2466  }
2467  else if (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE || !m_sendAckEvent.IsRunning ())
2468  {
2471  firsthdr.GetQosTid (),
2472  firsthdr.GetAddr2 (),
2473  firsthdr.GetDuration (),
2474  txVector,
2475  rxSnr);
2476  }
2477 
2478  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2479  {
2480  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2481  }
2482  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2483  {
2484  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2485  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2486  if (firsthdr.IsQosAck ())
2487  {
2488  NS_LOG_DEBUG ("Normal Ack");
2489  normalAck = true;
2490  }
2491  }
2492  else
2493  {
2494  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2495  }
2496 
2497  if (ampdu.GetRemainingNbOfMpdus () == 0 && !singleMpdu)
2498  {
2499  if (normalAck)
2500  {
2501  //send block Ack
2502  if (firsthdr.IsBlockAckReq ())
2503  {
2504  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2505  }
2506  uint8_t tid = firsthdr.GetQosTid ();
2507  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2508  if (it != m_bAckAgreements.end ())
2509  {
2510  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2511  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2512  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2514  }
2515  else
2516  {
2517  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2518  }
2519  }
2520  }
2521  }
2522  }
2523  else
2524  {
2525  ReceiveOk (aggregatedPacket, rxSnr, txVector, ampduSubframe);
2526  }
2527 }
2528 
2529 bool
2530 MacLow::StopMpduAggregation (Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint8_t blockAckSize) const
2531 {
2532  if (peekedPacket == 0)
2533  {
2534  NS_LOG_DEBUG ("no more packets in queue");
2535  return true;
2536  }
2537 
2538  Time aPPDUMaxTime = MicroSeconds (5484);
2539  uint8_t tid = GetTid (peekedPacket, peekedHdr);
2540  AcIndex ac = QosUtilsMapTidToAc (tid);
2541  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2542 
2543  if (m_phy->GetGreenfield ())
2544  {
2545  aPPDUMaxTime = MicroSeconds (10000);
2546  }
2547 
2548  //A STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime
2549  if (m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, m_currentTxVector, m_phy->GetFrequency ()) > aPPDUMaxTime)
2550  {
2551  NS_LOG_DEBUG ("no more packets can be aggregated to satisfy PPDU <= aPPDUMaxTime");
2552  return true;
2553  }
2554 
2555  if (!edcaIt->second->GetMpduAggregator ()->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, blockAckSize))
2556  {
2557  NS_LOG_DEBUG ("no more packets can be aggregated because the maximum A-MPDU size has been reached");
2558  return true;
2559  }
2560 
2561  return false;
2562 }
2563 
2566 {
2567  bool isAmpdu = false;
2568  Ptr<Packet> newPacket, tempPacket;
2569  WifiMacHeader peekedHdr;
2570  newPacket = packet->Copy ();
2571  Ptr<Packet> currentAggregatedPacket;
2572  CtrlBAckRequestHeader blockAckReq;
2573 
2574  if (hdr.IsBlockAckReq ())
2575  {
2576  //Workaround to avoid BlockAckReq to be part of an A-MPDU. The standard says that
2577  //BlockAckReq is not present in A-MPDU if any QoS data frames for that TID are present.
2578  //Since an A-MPDU in non-PSMP frame exchanges aggregates MPDUs from one TID, this means
2579  //we should stop aggregation here for single-TID A-MPDUs. Once PSMP and multi-TID A-MPDUs
2580  //are supported, the condition of entering here should be changed.
2581  return newPacket;
2582  }
2583 
2584  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2585  if (hdr.IsQosData () || hdr.IsBlockAck ()|| hdr.IsBlockAckReq ())
2586  {
2587  Time tstamp;
2588  uint8_t tid = GetTid (packet, hdr);
2589  Ptr<WifiMacQueue> queue;
2590  Ptr<Packet> aggPacket;
2591  AcIndex ac = QosUtilsMapTidToAc (tid);
2592  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2593  NS_ASSERT (edcaIt != m_edca.end ());
2594  queue = edcaIt->second->GetWifiMacQueue ();
2595 
2596  if (!hdr.GetAddr1 ().IsBroadcast () && edcaIt->second->GetMpduAggregator () != 0)
2597  {
2598  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2599  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2600  {
2601  /* here is performed mpdu aggregation */
2602  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2603  currentAggregatedPacket = Create<Packet> ();
2604  peekedHdr = hdr;
2605  uint16_t startingSequenceNumber = 0;
2606  uint16_t currentSequenceNumber = 0;
2607  uint8_t qosPolicy = 0;
2608  uint8_t blockAckSize = 0;
2609  bool aggregated = false;
2610  uint8_t i = 0;
2611  aggPacket = newPacket->Copy ();
2612 
2613  if (!hdr.IsBlockAckReq ())
2614  {
2615  if (!hdr.IsBlockAck ())
2616  {
2617  startingSequenceNumber = peekedHdr.GetSequenceNumber ();
2618  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2619  }
2620  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2621  newPacket->AddHeader (peekedHdr);
2622  AddWifiMacTrailer (newPacket);
2623 
2624  aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2625 
2626  if (aggregated)
2627  {
2628  NS_LOG_DEBUG ("Adding packet with sequence number " << currentSequenceNumber << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2629  i++;
2630  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2631  }
2632  }
2633  else if (hdr.IsBlockAckReq ())
2634  {
2635  blockAckSize = static_cast<uint8_t> (packet->GetSize () + hdr.GetSize () + WIFI_MAC_FCS_LENGTH);
2636  qosPolicy = 3; //if the last subframe is block ack req then set ack policy of all frames to blockack
2637  packet->PeekHeader (blockAckReq);
2638  startingSequenceNumber = blockAckReq.GetStartingSequence ();
2639  }
2641  bool retry = false;
2642  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
2643  Ptr<const Packet> peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, tid, &tstamp);
2644  if (peekedPacket == 0)
2645  {
2646  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2648  hdr.GetAddr1 ());
2649  if (item)
2650  {
2651  peekedPacket = item->GetPacket ();
2652  peekedHdr = item->GetHeader ();
2653  tstamp = item->GetTimeStamp ();
2654  }
2655  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2656 
2657  /* here is performed MSDU aggregation (two-level aggregation) */
2658  if (peekedPacket != 0 && edcaIt->second->GetMsduAggregator () != 0)
2659  {
2660  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2661  if (tempPacket != 0) //MSDU aggregation
2662  {
2663  peekedPacket = tempPacket->Copy ();
2664  }
2665  }
2666  }
2667  else
2668  {
2669  retry = true;
2670  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2671  }
2672 
2673  while (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopMpduAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
2674  {
2675  //for now always send AMPDU with normal ACK
2676  if (retry == false)
2677  {
2678  currentSequenceNumber = edcaIt->second->GetNextSequenceNumberFor (&peekedHdr);
2679  peekedHdr.SetSequenceNumber (currentSequenceNumber);
2680  peekedHdr.SetFragmentNumber (0);
2681  peekedHdr.SetNoMoreFragments ();
2682  peekedHdr.SetNoRetry ();
2683  }
2684  if (qosPolicy == 0)
2685  {
2686  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2687  }
2688  else
2689  {
2690  peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
2691  }
2692 
2693  newPacket = peekedPacket->Copy ();
2694  aggPacket = newPacket->Copy ();
2695 
2696  newPacket->AddHeader (peekedHdr);
2697  AddWifiMacTrailer (newPacket);
2698  aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2699  if (aggregated)
2700  {
2701  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2702  if (i == 1 && hdr.IsQosData ())
2703  {
2704  if (!m_txParams.MustSendRts ())
2705  {
2706  edcaIt->second->CompleteMpduTx (packet, hdr, tstamp);
2707  }
2708  else
2709  {
2710  InsertInTxQueue (packet, hdr, tstamp, tid);
2711  }
2712  }
2713  NS_LOG_DEBUG ("Adding packet with sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2714  i++;
2715  isAmpdu = true;
2716  if (!m_txParams.MustSendRts ())
2717  {
2718  edcaIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
2719  }
2720  else
2721  {
2722  InsertInTxQueue (peekedPacket, peekedHdr, tstamp, tid);
2723  }
2724  if (retry)
2725  {
2726  edcaIt->second->RemoveRetransmitPacket (tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
2727  }
2728  else
2729  {
2730  queue->Remove (peekedPacket);
2731  }
2732  newPacket = 0;
2733  }
2734  else
2735  {
2736  break;
2737  }
2738  if (retry == true)
2739  {
2740  peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, tid, &tstamp);
2741  if (peekedPacket == 0)
2742  {
2743  //I reached the first packet that I added to this A-MPDU
2744  retry = false;
2745  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2747  hdr.GetAddr1 ());
2748  if (item != 0)
2749  {
2750  peekedPacket = item->GetPacket ();
2751  peekedHdr = item->GetHeader ();
2752  tstamp = item->GetTimeStamp ();
2753  //find what will the sequence number be so that we don't send more than 64 packets apart
2754  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2755 
2756  if (edcaIt->second->GetMsduAggregator () != 0)
2757  {
2758  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2759  if (tempPacket != 0) //MSDU aggregation
2760  {
2761  peekedPacket = tempPacket->Copy ();
2762  }
2763  }
2764  }
2765  }
2766  else
2767  {
2768  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2769  }
2770  }
2771  else
2772  {
2773  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2774  WifiMacHeader::ADDR1, hdr.GetAddr1 ());
2775  if (item != 0)
2776  {
2777  peekedPacket = item->GetPacket ();
2778  peekedHdr = item->GetHeader ();
2779  tstamp = item->GetTimeStamp ();
2780  //find what will the sequence number be so that we don't send more than 64 packets apart
2781  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2782 
2783  if (edcaIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
2784  {
2785  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2786  if (tempPacket != 0) //MSDU aggregation
2787  {
2788  peekedPacket = tempPacket->Copy ();
2789  }
2790  }
2791  }
2792  else
2793  {
2794  peekedPacket = 0;
2795  }
2796  }
2797  }
2798 
2799  if (isAmpdu)
2800  {
2801  if (hdr.IsBlockAckReq ())
2802  {
2803  newPacket = packet->Copy ();
2804  peekedHdr = hdr;
2805  aggPacket = newPacket->Copy ();
2806  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2807  newPacket->AddHeader (peekedHdr);
2808  AddWifiMacTrailer (newPacket);
2809  edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2810  currentAggregatedPacket->AddHeader (blockAckReq);
2811  }
2812 
2813  if (qosPolicy == 0)
2814  {
2815  edcaIt->second->CompleteAmpduTransfer (hdr.GetAddr1 (), tid);
2816  }
2817 
2818  //Add packet tag
2819  AmpduTag ampdutag;
2820  ampdutag.SetRemainingNbOfMpdus (i - 1);
2821  newPacket = currentAggregatedPacket;
2822  newPacket->AddPacketTag (ampdutag);
2823 
2824  NS_LOG_DEBUG ("tx unicast A-MPDU");
2825  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2826  }
2827  else
2828  {
2829  uint32_t queueSize = m_aggregateQueue[tid]->GetNPackets ();
2830  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
2831  if (queueSize >= 1)
2832  {
2833  //remove any packets that we added to the aggregate queue
2834  FlushAggregateQueue (tid);
2835  }
2836  }
2837  }
2838  // VHT/HE single MPDU operation
2840  if (!isAmpdu
2841  && hdr.IsQosData ()
2842  && (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT
2843  || dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HE))
2844  {
2845  peekedHdr = hdr;
2847 
2848  currentAggregatedPacket = Create<Packet> ();
2849  edcaIt->second->GetMpduAggregator ()->AggregateSingleMpdu (packet, currentAggregatedPacket);
2850  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (packet, peekedHdr));
2851  if (m_txParams.MustSendRts ())
2852  {
2853  InsertInTxQueue (packet, peekedHdr, tstamp, tid);
2854  }
2855  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2856  {
2857  edcaIt->second->CompleteAmpduTransfer (peekedHdr.GetAddr1 (), tid);
2858  }
2859 
2860  //Add packet tag
2861  AmpduTag ampdutag;
2862  newPacket = currentAggregatedPacket;
2863  newPacket->AddHeader (peekedHdr);
2864  AddWifiMacTrailer (newPacket);
2865  newPacket->AddPacketTag (ampdutag);
2866 
2867  NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ());
2868  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2869  }
2870  }
2871  }
2872  return newPacket;
2873 }
2874 
2875 void
2877 {
2878  if (!m_aggregateQueue[tid]->IsEmpty ())
2879  {
2880  NS_LOG_DEBUG ("Flush aggregate queue");
2881  m_aggregateQueue[tid]->Flush ();
2882  }
2883  m_txPackets[tid].clear ();
2884 }
2885 
2886 void
2887 MacLow::InsertInTxQueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
2888 {
2889  NS_LOG_FUNCTION (this);
2890  Item item;
2891  item.packet = packet;
2892  item.hdr = hdr;
2893  item.timestamp = tStamp;
2894  m_txPackets[tid].push_back (item);
2895 }
2896 
2898 MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint8_t blockAckSize)
2899 {
2900  bool msduAggregation = false;
2901  bool isAmsdu = false;
2902  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
2903  Ptr<Packet> tempPacket = Create<Packet> ();
2904 
2905  Ptr<WifiMacQueue> queue;
2906  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
2907  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2908  NS_ASSERT (edcaIt != m_edca.end ());
2909  queue = edcaIt->second->GetWifiMacQueue ();
2910 
2911  Ptr<const WifiMacQueueItem> peekedItem = queue->DequeueByTidAndAddress (hdr->GetQosTid (),
2913  hdr->GetAddr1 ());
2914  if (peekedItem)
2915  {
2916  *hdr = peekedItem->GetHeader ();
2917  }
2918 
2919  edcaIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
2920  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2921  edcaIt->second->MapDestAddressForAggregation (*hdr));
2922 
2923  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
2924  while (peekedItem != 0)
2925  {
2926  *hdr = peekedItem->GetHeader ();
2927  *tstamp = peekedItem->GetTimeStamp ();
2928  tempPacket = currentAmsduPacket;
2929 
2930  msduAggregation = edcaIt->second->GetMsduAggregator ()->Aggregate (peekedItem->GetPacket (), tempPacket,
2931  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2932  edcaIt->second->MapDestAddressForAggregation (*hdr));
2933 
2934  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
2935  {
2936  isAmsdu = true;
2937  currentAmsduPacket = tempPacket;
2938  queue->Remove (peekedItem->GetPacket ());
2939  }
2940  else
2941  {
2942  break;
2943  }
2944  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
2945  }
2946 
2947  if (isAmsdu)
2948  {
2949  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
2950  hdr->SetQosAmsdu ();
2951  hdr->SetAddr3 (GetBssid ());
2952  return currentAmsduPacket;
2953  }
2954  else
2955  {
2956  queue->PushFront (Create<WifiMacQueueItem> (packet, *hdr));
2957  return 0;
2958  }
2959 }
2960 
2961 Time
2963 {
2964  NS_LOG_FUNCTION (this);
2966  NS_ASSERT (remainingCfpDuration.IsPositive ());
2967  return remainingCfpDuration;
2968 }
2969 
2970 bool
2972 {
2974 }
2975 
2976 bool
2978 {
2979  NS_LOG_FUNCTION (this);
2980  if (!IsCfPeriod ())
2981  {
2982  return false;
2983  }
2984  NS_ASSERT (GetRemainingCfpDuration ().IsPositive ());
2985  WifiMacHeader hdr;
2986  hdr.SetType (WIFI_MAC_DATA);
2987  WifiMacTrailer fcs;
2988  uint32_t maxMacFrameSize = MAX_MSDU_SIZE + hdr.GetSerializedSize () + fcs.GetSerializedSize ();
2990  return ((GetRemainingCfpDuration () - nextTransmission).IsPositive ());
2991 }
2992 
2993 } //namespace ns3
void WaitIfsAfterEndTxPacket(void)
Event handler that is usually scheduled to fired at the appropriate time after sending a packet...
Definition: mac-low.cc:1983
bool IsBeacon(void) const
Return true if the header is a Beacon header.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:83
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:420
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:334
Time m_ctsTimeout
CTS timeout duration.
Definition: mac-low.h:916
uint16_t GetBufferSize(void) const
Return the buffer size.
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
EventId m_navCounterResetCtsMissed
Event to reset NAV when CTS is not received.
Definition: mac-low.h:904
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
bool IsPositive(void) const
Definition: nstime.h:298
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:156
std::vector< Ptr< ChannelAccessManager > >::const_iterator ChannelAccessManagersCI
typedef for an iterator for a list of ChannelAccessManager.
Definition: mac-low.h:889
Ptr< WifiPhy > GetPhy(void) const
Definition: mac-low.cc:259
void SetRawDuration(uint16_t duration)
Set the Duration/ID field with the given raw uint16_t value.
void ResetBlockAckInactivityTimerIfNeeded(BlockAckAgreement &agreement)
Every time that a block ack request or a packet with ack policy equals to block ack are received...
Definition: mac-low.cc:2419
virtual bool IsCfPeriod(void) const
This function indicates whether it is the CF period.
Definition: mac-low.cc:2971
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:897
Callback template class.
Definition: callback.h:1176
bool IsCfEnd(void) const
Return true if the header is a CF-END header.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
std::vector< Item > m_txPackets[8]
Contain temporary items to be sent with the next A-MPDU transmission for a given TID, once RTS/CTS exchange has succeeded.
Definition: mac-low.h:960
uint8_t GetRemainingNbOfMpdus(void) const
Definition: ampdu-tag.cc:89
uint16_t GetTimeout(void) const
Return the timeout.
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the ACK (including preamble and FCS).
Definition: mac-low.cc:1106
void SendBlockAckAfterBlockAckRequest(const CtrlBAckRequestHeader reqHdr, Mac48Address originator, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
Invoked after that a block ack request has been received.
Definition: mac-low.cc:2355
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
uint16_t GetRawDuration(void) const
Return the raw duration from the Duration/ID field.
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
void SetPromisc(void)
Enable promiscuous mode.
Definition: mac-low.cc:364
bool GetGreenfield(void) const
Return whether Greenfield is supported.
Definition: wifi-phy.cc:596
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:156
#define min(a, b)
Definition: 80211b.c:42
virtual void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: txop.cc:813
void DoNavResetNow(Time duration)
Reset NAV with the given duration.
Definition: mac-low.cc:1283
Ptr< Txop > m_currentTxop
Current TXOP.
Definition: mac-low.h:908
virtual void EndTxNoAck(void)
Event handler when a transmission that does not require an ACK has completed.
Definition: txop.cc:715
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
void NotifyMaybeCcaBusyStart(Time duration)
Definition: mac-low.cc:80
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:444
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
void SetupPhyMacLowListener(const Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:154
virtual void StartNextFragment(void)
Start transmission for the next fragment.
Definition: txop.cc:686
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:134
Mac48Address GetPeer(void) const
Return the peer address.
bool IsStateRx(void) const
Definition: wifi-phy.cc:3531
bool IsZero(void) const
Definition: nstime.h:288
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:919
void SetPhy(const Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:250
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:852
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added...
Definition: wifi-utils.cc:163
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1295
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:426
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:322
void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:83
void ForwardDown(Ptr< const Packet > packet, const WifiMacHeader *hdr, WifiTxVector txVector)
Forward the packet down to WifiPhy for transmission.
Definition: mac-low.cc:1349
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef
Definition: mac-low.h:943
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:412
virtual void MissedAck(void)
Event handler when an ACK is missed.
Definition: txop.cc:620
WifiTxVector GetCtsTxVector(Mac48Address address, WifiMode rtsMode)
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1181
#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
void Init(uint16_t winStart, uint16_t winSize)
Init function.
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:202
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
static DeaggregatedMpdus Deaggregate(Ptr< Packet > aggregatedPacket)
Deaggregates an A-MPDU by removing the A-MPDU subframe header and padding.
bool IsBroadcast(void) const
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:673
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:658
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Notify NAV function.
Definition: mac-low.cc:1230
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
std::list< std::pair< Ptr< Packet >, AmpduSubframeHeader > >::const_iterator DeaggregatedMpdusCI
A constant iterator for a list of deaggregated packets and their A-MPDU subframe headers.
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
Sends DELBA frame to cancel a block ack agreement with sta addressed by addr for tid tid...
Definition: qos-txop.cc:1505
void UnregisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:424
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet. ...
Definition: qos-utils.cc:83
void SendPacket(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype=NORMAL_MPDU)
Definition: wifi-phy.cc:2280
virtual void Cancel(void)
Cancel the transmission.
Definition: txop.cc:708
uint32_t GetAckSize(void)
Return the total ACK size (including FCS trailer).
Definition: wifi-utils.cc:104
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:733
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
bool m_ampdu
Flag if the current transmission involves an A-MPDU.
Definition: mac-low.h:933
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
bool NeedRts(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, WifiTxVector txVector)
void SetRxCallback(Callback< void, Ptr< Packet >, const WifiMacHeader * > callback)
Definition: mac-low.cc:450
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:388
Callback< R > MakeNullCallback(void)
Definition: callback.h:1635
bool StopMpduAggregation(Ptr< const Packet > peekedPacket, WifiMacHeader peekedHdr, Ptr< Packet > aggregatedPacket, uint8_t blockAckSize) const
Definition: mac-low.cc:2530
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:912
ns3::Time timeout
Ptr< Packet > AggregateToAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Definition: mac-low.cc:2565
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:899
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, Ptr< Txop > txop)
Definition: mac-low.cc:478
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:864
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:394
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void DeaggregateAmpduAndReceive(Ptr< Packet > aggregatedPacket, double rxSnr, WifiTxVector txVector)
Definition: mac-low.cc:2441
bool appendCfAck
Flag used for PCF to indicate whether a CF-ACK should be appended.
Definition: mac-low.h:881
EventId m_sendAckEvent
Event to send ACK.
Definition: mac-low.h:900
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1235
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1130
Time m_cfpMaxDuration
CFP max duration.
Definition: mac-low.h:923
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
control how a packet is transmitted.
MpduType
The type of an MPDU.
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:304
bool expectCfAck
Flag used for PCF to indicate whether a CF-ACK should be expected.
Definition: mac-low.h:882
QueueEdcas m_edca
EDCA queues.
Definition: mac-low.h:956
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1517
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:292
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
phy
Definition: third.py:86
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:953
bool HasData(void) const
Return true if the header type is DATA and is not DATA_NULL.
Time timestamp
the timestamp
Definition: mac-low.h:873
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
void RemovePhyMacLowListener(Ptr< WifiPhy > phy)
Remove current WifiPhy listener for this MacLow.
Definition: mac-low.cc:161
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2226
void NotifyOn(void)
Notify listeners that we went to switch on.
Definition: mac-low.cc:98
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:961
The MPDU is not part of an A-MPDU.
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2156
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:874
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:926
uint32_t GetSerializedSize(void) const
void SetCfpMaxDuration(Time duration)
Definition: mac-low.cc:352
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
std::pair< Ptr< Packet >, WifiMacHeader > BufferedPacket
buffered packet typedef
Definition: mac-low.h:940
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:1789
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:958
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send ACK after receiving DATA.
Definition: mac-low.cc:2009
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1381
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
#define max(a, b)
Definition: 80211b.c:43
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2114
Time m_lastBeacon
The time when the last beacon frame transmission started.
Definition: mac-low.h:929
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
void ReportRtsFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
Listener for PHY events.
Definition: mac-low.cc:53
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1031
receive notifications about phy events.
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1502
static const uint16_t MAX_MSDU_SIZE
This value conforms to the 802.11 specification.
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
uint32_t GetCfEndSize(void) const
Return the total CF-END size (including FCS trailer).
Definition: mac-low.cc:1084
void EndTxNoAck(void)
A transmission that does not require an ACK has completed.
Definition: mac-low.cc:1990
void SendBlockAckAfterAmpdu(uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
Invoked after an A-MPDU has been received.
Definition: mac-low.cc:2325
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
block ack caches iterator typedef
Definition: mac-low.h:950
WifiTxVector GetAckTxVector(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the ACK frame given the destination and the mode of the DATA used by the sender...
Definition: mac-low.cc:1157
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:286
static TypeId GetTypeId(void)
Register this type.
Definition: mac-low.cc:143
indicates whether the socket has a priority set.
Definition: socket.h:1303
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:31
Time GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:407
HT PHY (Clause 20)
Definition: wifi-mode.h:58
void NavCounterResetCtsMissed(Time rtsEndRxTime)
Reset NAV after CTS was missed when the NAV was set with RTS.
Definition: mac-low.cc:1274
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:863
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
Headers for Block ack response.
Definition: ctrl-headers.h:181
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:370
void SendDataAfterCts(Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:1890
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2435
Agreements m_bAckAgreements
block ack agreements
Definition: mac-low.h:952
Ptr< WifiMacQueue > m_aggregateQueue[8]
Queues per TID used for MPDU aggregation.
Definition: mac-low.h:959
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
void SendMpdu(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype)
Forward the MPDU down to WifiPhy for transmission.
Definition: mac-low.cc:1477
The aim of the AmpduTag is to provide means for a MAC to specify that a packet includes A-MPDU since ...
Definition: ampdu-tag.h:36
WifiTxVector GetAckTxVectorForData(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the Block ACK frame given the destination and the mode of the DATA used by the ...
Definition: mac-low.cc:1175
bool IsMgt(void) const
Return true if the Type is Management.
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:642
void NotifyOff(void)
Notify listeners that we went to switch off.
Definition: mac-low.cc:91
Time m_slotTime
Slot duration.
Definition: mac-low.h:918
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:932
void NotifyRxStart(Time duration)
Definition: mac-low.cc:68
WifiMacHeader hdr
the header
Definition: mac-low.h:872
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:198
void ReportDataOk(Mac48Address address, const WifiMacHeader *header, double ackSnr, WifiMode ackMode, double dataSnr)
Should be invoked whenever we receive the Ack associated to a data packet we just sent...
std::list< BufferedPacket >::iterator BufferedPacketI
buffered packet iterator typedef
Definition: mac-low.h:941
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1536
void NotifyCtsTimeoutStartNow(Time duration)
Notify ChannelAccessManager that CTS timer should be started for the given duration.
Definition: mac-low.cc:1331
The MPDU is part of an A-MPDU, but is not the last aggregate.
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
virtual bool HasTxop(void) const
Check if the station has TXOP granted for the next MPDU.
Definition: txop.cc:831
void EnableCompressedBlockAck(void)
Wait COMPRESSEDBLOCKACKTimeout for a Compressed Block Ack Response frame.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void GotCfEnd(void)
Event handler when a CF-END frame is received.
Definition: txop.cc:647
void RegisterDcf(Ptr< ChannelAccessManager > dcf)
Definition: mac-low.cc:456
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:358
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
EventId m_waitIfsEvent
Wait for IFS event.
Definition: mac-low.h:902
void ReceiveOk(Ptr< Packet > packet, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
Definition: mac-low.cc:688
void EnableAck(void)
Wait ACKTimeout for an ACK.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
virtual void MissedBlockAck(uint8_t nMpdus)
Event handler when a Block ACK timeout has occurred.
Definition: txop.cc:825
Time CalculateTransmissionTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &parameters) const
Definition: mac-low.cc:1215
EventId m_normalAckTimeoutEvent
Normal ACK timeout event.
Definition: mac-low.h:896
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a DATA timer by scheduling appropriate ACK timeout.
Definition: mac-low.cc:1613
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:95
void SetType(BlockAckType type)
Set the block ACK type.
Time m_beaconInterval
Expected interval between two beacon transmissions.
Definition: mac-low.h:922
void NotifyCtsTimeoutResetNow()
Notify ChannelAccessManager that CTS timer should be reset.
Definition: mac-low.cc:1340
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:150
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:318
an EUI-48 address
Definition: mac48-address.h:43
Ptr< const Packet > packet
the packet
Definition: mac-low.h:871
Time GetLastRxStartTime(void) const
Return the start time of the last received packet.
Definition: wifi-phy.cc:3567
Time m_cfpForeshortening
The delay the current CF period should be foreshortened.
Definition: mac-low.h:930
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:77
void SendBlockAckResponse(const CtrlBAckResponseHeader *blockAck, Mac48Address originator, bool immediate, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
This method creates block ack frame with header equals to blockAck and start its transmission.
Definition: mac-low.cc:2264
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:913
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:98
bool NeedRts(void) const
Check if the current packet should be sent with a RTS protection.
Definition: mac-low.cc:606
void DisableRts(void)
Do not send rts and wait for cts before sending data.
bool IsCfPoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
void ReportRtsOk(Mac48Address address, const WifiMacHeader *header, double ctsSnr, WifiMode ctsMode, double rtsSnr)
Should be invoked whenever we receive the Cts associated to an RTS we just sent.
EventId m_ctsTimeoutEvent
CTS timeout event.
Definition: mac-low.h:898
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2172
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:1858
bool CanTransmitNextCfFrame(void) const
This function decides if a CF frame can be transmitted in the current CFP.
Definition: mac-low.cc:2977
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:914
bool IsStateTx(void) const
Definition: wifi-phy.cc:3537
uint16_t GetTimeout(void) const
Return the timeout.
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:290
void FlushAggregateQueue(uint8_t tid)
This function is called to flush the aggregate queue, which is used for A-MPDU.
Definition: mac-low.cc:2876
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
Time GetCfpMaxDuration(void) const
Definition: mac-low.cc:438
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:917
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
Time GetSlotTime(void) const
Return slot duration of this MacLow.
Definition: mac-low.cc:414
void SetBeaconInterval(Time interval)
Definition: mac-low.cc:346
WifiMacHeader m_lastReceivedHdr
Header of the last received packet.
Definition: mac-low.h:909
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
WifiPreamble GetPreambleType(void) const
void NotifySleep(void)
Notify listeners that we went to sleep.
Definition: mac-low.cc:87
uint32_t GetCtsSize(void)
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:142
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:925
EventId m_inactivityEvent
inactivity event
bool NeedCtsToSelf(WifiTxVector txVector)
Return if we need to do Cts-to-self before sending a DATA.
void ReceiveError(Ptr< Packet > packet, double rxSnr)
Definition: mac-low.cc:621
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
WifiTxVector GetRtsTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1137
virtual WifiTxVector GetDataTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the DATA frame given the destination.
Definition: mac-low.cc:1144
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:58
Mac48Address address
Address of the station to be acknowledged.
Definition: mac-low.h:883
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:406
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:901
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:418
bool ReceiveMpdu(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:2041
bool HasHeSupported(void) const
Return whether the device has HE capability support enabled.
void NotifyRxEndError(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:74
MacLowTransmissionParameters m_txParams
Transmission parameters of the current packet.
Definition: mac-low.h:910
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:340
void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:172
void NotifyAckTimeoutResetNow()
Notify ChannelAccessManager that ACK timer should be reset.
Definition: mac-low.cc:1322
WifiTxVector GetDataTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:388
WifiTxVector GetBlockAckTxVector(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the Block ACK frame given the destination and the mode of the DATA used by the ...
Definition: mac-low.cc:1163
bool IsData(void) const
Return true if the Type is DATA.
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:911
Maintains information for a block ack agreement.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
uint32_t QosUtilsMapSeqControlToUniqueInteger(uint16_t seqControl, uint16_t endSequence)
Next function is useful to correctly sort buffered packets under block ack.
Definition: qos-utils.cc:72
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:1783
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
Time GetBlockAckDuration(WifiTxVector blockAckReqTxVector, BlockAckType type) const
Return the time required to transmit the Block ACK to the specified address given the TXVECTOR of the...
Definition: mac-low.cc:1113
void NotifyAckTimeoutStartNow(Time duration)
Notify ChannelAccessManager that ACK timer should be started for the given duration.
Definition: mac-low.cc:1313
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
void SetSlotTime(Time slotTime)
Set slot duration of this MacLow.
Definition: mac-low.cc:328
virtual void GotAck(void)
Event handler when an ACK is received.
Definition: txop.cc:593
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:906
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:400
bool NeedCtsToSelf(void) const
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:614
void Reset(void)
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot. ...
virtual void MissedCts(void)
Event handler when a CTS timeout has occurred.
Definition: txop.cc:568
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:859
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1129
bool GetRifsPermitted(void) const
Return whether the device can use RIFS.
Time m_cfpStart
The time when the latest CF period started.
Definition: mac-low.h:928
ns3::MacLow * m_macLow
the MAC
Definition: mac-low.cc:103
The MPDU is the last aggregate in an A-MPDU.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
uint32_t GetBlockAckSize(BlockAckType type)
Return the total Block ACK size (including FCS trailer).
Definition: wifi-utils.cc:112
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
Time GetBeaconInterval(void) const
Definition: mac-low.cc:432
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
agreements iterator
Definition: mac-low.h:947
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:903
bool IsStateOff(void) const
Definition: wifi-phy.cc:3555
void MissedCfPollResponse(bool expectedCfAck)
Event handler when a response to a CF-POLL frame is missed.
Definition: txop.cc:661
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:310
CfAckInfo m_cfAckInfo
Info about piggyback ACKs used in PCF.
Definition: mac-low.h:963
void ReportRxOk(Mac48Address address, const WifiMacHeader *header, double rxSnr, WifiMode txMode)
void NotifyRxEndOk(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:71
std::list< std::pair< Ptr< Packet >, AmpduSubframeHeader > > DeaggregatedMpdus
A list of deaggregated packets and their A-MPDU subframe headers.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
void SetCtsTimeout(Time ctsTimeout)
Set CTS timeout of this MacLow.
Definition: mac-low.cc:316
bool HasPcfSupported(void) const
Return whether the device has PCF capability support enabled.
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:376
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
void SendDataPacket(void)
Send DATA packet, which can be DATA-ACK or RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1672
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1023
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:907
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:280
second
Definition: nstime.h:114
bool IsCts(void) const
Return true if the header is a CTS header.
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
WifiTxVector GetRtsTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
A base class which provides memory management and object aggregation.
Definition: object.h:87
void WaitIfsAfterEndTxFragment(void)
Event handler that is usually scheduled to fired at the appropriate time after completing transmissio...
Definition: mac-low.cc:1976
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:61
Ptr< Packet > PerformMsduAggregation(Ptr< const Packet > packet, WifiMacHeader *hdr, Time *tstamp, Ptr< Packet > currentAmpduPacket, uint8_t blockAckSize)
Perform MSDU aggregation for a given MPDU in an A-MPDU.
Definition: mac-low.cc:2898
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:500
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:915
void CfPollTimeout(void)
Event handler when CF-POLL timeout occurs.
Definition: mac-low.cc:1484
WifiMode GetMode(void) const
Time GetRemainingCfpDuration(void) const
Definition: mac-low.cc:2962
void SetRemainingNbOfMpdus(uint8_t nbofmpdus)
Definition: ampdu-tag.cc:52
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
bool IsRts(void) const
Return true if the header is a RTS header.
Headers for Block ack request.
Definition: ctrl-headers.h:41
bool IsAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Checks if the given packet will be aggregated to an A-MPDU or not.
Definition: mac-low.cc:462
bool IsAck(void) const
Return true if the header is an ACK header.
void InsertInTxQueue(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
Insert in a temporary queue.
Definition: mac-low.cc:2887
virtual ~PhyMacLowListener()
Definition: mac-low.cc:65
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:265
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
Event handler when a Block ACK is received.
Definition: txop.cc:819
void DisableAck(void)
Do not wait for Ack after data transmission.
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
std::pair< BlockAckAgreement, std::list< BufferedPacket > > AgreementValue
agreement value typedef
Definition: mac-low.h:944
WifiTxVector GetCtsTxVectorForRts(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender...
Definition: mac-low.cc:1169
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:382
a unique identifier for an interface.
Definition: type-id.h:58
WifiTxVector GetAckTxVector(Mac48Address address, WifiMode dataMode)
BlockAckCache cache.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
Time GetRemainingAmpduDuration(void) const
Definition: ampdu-tag.cc:95
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
void SetQosAmsdu(void)
Set that A-MSDU is present.
Time m_rifs
Reduced Interframe Space (RIFS) duration.
Definition: mac-low.h:920
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:37
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:688
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender...
Definition: mac-low.cc:1151
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
bool StoreMpduIfNeeded(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:2085
HE PHY (Clause 26)
Definition: wifi-mode.h:62
virtual ~MacLow()
Definition: mac-low.cc:136
A struct for packet, Wifi header, and timestamp.item structure.
Definition: mac-low.h:869
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:862
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:274
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void SetCompressedBlockAckTimeout(Time blockAckTimeout)
Set Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:298
Implements the IEEE 802.11 MAC trailer.
bool IsQosAck(void) const
Return if the QoS ACK policy is Normal ACK.
class PhyMacLowListener * m_phyMacLowListener
Listener needed to monitor when a channel switching occurs.
Definition: mac-low.h:935
ChannelAccessManagers m_channelAccessManagers
List of ChannelAccessManager.
Definition: mac-low.h:894
uint32_t GetSerializedSize(void) const
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
void SendRtsForPacket(void)
Send RTS to begin RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1551
BlockAckType
The different block ACK policies.
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2235
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
void SetRemainingAmpduDuration(Time duration)
Definition: ampdu-tag.cc:59
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.