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 {
157  phy->RegisterListener (m_phyMacLowListener);
158 }
159 
160 void
162 {
163  if (m_phyMacLowListener != 0 )
164  {
165  phy->UnregisterListener (m_phyMacLowListener);
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 
699  bool isPrevNavZero = IsNavZero ();
700  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
701  NotifyNav (packet, hdr);
702  if (hdr.IsRts ())
703  {
704  /* see section 9.2.5.7 802.11-1999
705  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
706  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
707  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
708  * that STA shall not respond to the RTS frame.
709  */
710  if (ampduSubframe)
711  {
712  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
713  }
714  else
715  {
716  if (isPrevNavZero
717  && hdr.GetAddr1 () == m_self)
718  {
719  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
721  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
722  rxSnr, txVector.GetMode ());
725  hdr.GetAddr2 (),
726  hdr.GetDuration (),
727  txVector,
728  rxSnr);
729  }
730  else
731  {
732  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
733  }
734  }
735  }
736  else if (hdr.IsCts ()
737  && hdr.GetAddr1 () == m_self
739  && m_currentPacket != 0)
740  {
741  if (ampduSubframe)
742  {
743  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
744  }
745 
746  NS_LOG_DEBUG ("received cts from=" << m_currentHdr.GetAddr1 ());
747 
748  SnrTag tag;
749  packet->RemovePacketTag (tag);
751  rxSnr, txVector.GetMode ());
753  rxSnr, txVector.GetMode (), tag.Get ());
754 
760  hdr.GetDuration ());
761  }
762  else if (hdr.IsAck ()
763  && hdr.GetAddr1 () == m_self
766  {
767  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
768  SnrTag tag;
769  packet->RemovePacketTag (tag);
770  //When fragmentation is used, only update manager when the last fragment is acknowledged
771  if (!m_txParams.HasNextPacket ())
772  {
774  rxSnr, txVector.GetMode ());
776  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  m_currentPacket->GetSize ());
1526  Ptr<Txop> txop = m_currentTxop;
1527  m_currentTxop = 0;
1528  m_ampdu = false;
1529  if (m_currentHdr.IsQosData ())
1530  {
1532  }
1533  txop->MissedAck ();
1534 }
1535 
1536 void
1538 {
1539  NS_LOG_FUNCTION (this);
1540  NS_LOG_DEBUG ("block ack timeout");
1541  Ptr<Txop> txop = m_currentTxop;
1542  m_currentTxop = 0;
1543  m_ampdu = false;
1544  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1545  AmpduTag ampdu;
1547  txop->MissedBlockAck (ampdu.GetRemainingNbOfMpdus () + 1);
1548  FlushAggregateQueue (tid);
1549 }
1550 
1551 void
1553 {
1554  NS_LOG_FUNCTION (this);
1555  /* send an RTS for this packet. */
1556  WifiMacHeader rts;
1557  rts.SetType (WIFI_MAC_CTL_RTS);
1558  rts.SetDsNotFrom ();
1559  rts.SetDsNotTo ();
1560  rts.SetNoRetry ();
1561  rts.SetNoMoreFragments ();
1562  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1563  rts.SetAddr2 (m_self);
1565  Time duration = Seconds (0);
1566 
1567  duration += GetSifs ();
1568  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1569  duration += GetSifs ();
1572  duration += GetSifs ();
1574  {
1576  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1577  }
1579  {
1581  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1582  }
1583  else if (m_txParams.MustWaitNormalAck ())
1584  {
1586  }
1587  if (m_txParams.HasNextPacket ())
1588  {
1592  {
1593  duration += GetSifs ();
1595  }
1596  }
1597  rts.SetDuration (duration);
1598 
1599  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1600  Time timerDelay = txDuration + GetCtsTimeout ();
1601 
1603  NotifyCtsTimeoutStartNow (timerDelay);
1605 
1606  Ptr<Packet> packet = Create<Packet> ();
1607  packet->AddHeader (rts);
1608  AddWifiMacTrailer (packet);
1609 
1610  ForwardDown (packet, &rts, rtsTxVector);
1611 }
1612 
1613 void
1615 {
1617  if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
1618  {
1619  Time timerDelay = txDuration + GetAckTimeout ();
1621  NotifyAckTimeoutStartNow (timerDelay);
1623  }
1624  else if (m_txParams.MustWaitBasicBlockAck ())
1625  {
1626  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1628  NotifyAckTimeoutStartNow (timerDelay);
1630  }
1632  {
1633  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1635  NotifyAckTimeoutStartNow (timerDelay);
1637  }
1638  else if (m_txParams.HasNextPacket ())
1639  {
1641  Time delay = txDuration;
1643  {
1644  delay += GetRifs ();
1645  }
1646  else
1647  {
1648  delay += GetSifs ();
1649  }
1651  }
1653  {
1654  Time delay = txDuration;
1656  {
1657  delay += GetRifs ();
1658  }
1659  else
1660  {
1661  delay += GetSifs ();
1662  }
1664  }
1665  else
1666  {
1667  // since we do not expect any timer to be triggered.
1669  }
1670 }
1671 
1672 void
1674 {
1675  NS_LOG_FUNCTION (this);
1676  /* send this packet directly. No RTS is needed. */
1678 
1679  if (!IsCfPeriod ())
1680  {
1681  Time duration = Seconds (0);
1683  {
1684  duration += GetSifs ();
1686  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1687  }
1689  {
1690  duration += GetSifs ();
1692  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1693  }
1694  else if (m_txParams.MustWaitNormalAck ())
1695  {
1696  duration += GetSifs ();
1698  }
1699  if (m_txParams.HasNextPacket ())
1700  {
1702  {
1703  duration += GetRifs ();
1704  }
1705  else
1706  {
1707  duration += GetSifs ();
1708  }
1712  {
1713  duration += GetSifs ();
1715  }
1716  }
1717  m_currentHdr.SetDuration (duration);
1718  }
1719  else
1720  {
1721  if (m_currentHdr.IsCfEnd ())
1722  {
1724  }
1725  else
1726  {
1727  m_currentHdr.SetRawDuration (32768);
1728  }
1729  }
1730 
1731  Ptr <Packet> packet = m_currentPacket->Copy ();
1732  if (m_ampdu)
1733  {
1735  }
1736  else
1737  {
1739  {
1740  switch (m_currentHdr.GetType ())
1741  {
1742  case WIFI_MAC_DATA:
1744  break;
1745  case WIFI_MAC_DATA_CFPOLL:
1747  break;
1748  case WIFI_MAC_DATA_NULL:
1750  break;
1753  break;
1754  case WIFI_MAC_CTL_END:
1756  break;
1757  default:
1758  NS_ASSERT (false);
1759  break;
1760  }
1762  //Standard says that, for frames of type Data+CF-ACK, Data+CF-Poll+CF-ACK, and CF-Poll+CF-ACK,
1763  //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.
1764  //This ideally requires the rate manager to handle this case, but this requires to update all rate manager classes.
1765  //Instead, we simply fetch two TxVector and we select the one with the lowest datarate.
1766  //This should be later changed, at the latest once HCCA is implemented for HT/VHT stations.
1767  WifiMacHeader tmpHdr = m_currentHdr;
1768  tmpHdr.SetAddr1 (m_cfAckInfo.address);
1769  WifiTxVector tmpTxVector = GetDataTxVector (packet, &tmpHdr);
1770  if (tmpTxVector.GetMode ().GetDataRate (tmpTxVector) < m_currentTxVector.GetMode ().GetDataRate (m_currentTxVector))
1771  {
1772  m_currentTxVector = tmpTxVector;
1773  }
1774  m_cfAckInfo.appendCfAck = false;
1776  }
1777  packet->AddHeader (m_currentHdr);
1778  AddWifiMacTrailer (packet);
1779  }
1781 }
1782 
1783 bool
1784 MacLow::IsNavZero (void) const
1785 {
1787 }
1788 
1789 void
1791 {
1792  WifiMacHeader cts;
1793  cts.SetType (WIFI_MAC_CTL_CTS);
1794  cts.SetDsNotFrom ();
1795  cts.SetDsNotTo ();
1796  cts.SetNoMoreFragments ();
1797  cts.SetNoRetry ();
1798  cts.SetAddr1 (m_self);
1799 
1801  Time duration = Seconds (0);
1802 
1803  duration += GetSifs ();
1807  {
1808  duration += GetSifs ();
1810  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1811  }
1813  {
1814  duration += GetSifs ();
1816  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1817  }
1818  else if (m_txParams.MustWaitNormalAck ())
1819  {
1820  duration += GetSifs ();
1822  }
1823  if (m_txParams.HasNextPacket ())
1824  {
1825  duration += GetSifs ();
1829  {
1830  duration += GetSifs ();
1832  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1833  }
1834  else if (m_txParams.MustWaitNormalAck ())
1835  {
1836  duration += GetSifs ();
1838  }
1839  }
1840 
1841  cts.SetDuration (duration);
1842 
1843  Ptr<Packet> packet = Create<Packet> ();
1844  packet->AddHeader (cts);
1845  AddWifiMacTrailer (packet);
1846 
1847  ForwardDown (packet, &cts, ctsTxVector);
1848 
1849  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1850  txDuration += GetSifs ();
1852 
1853  m_sendDataEvent = Simulator::Schedule (txDuration,
1854  &MacLow::SendDataAfterCts, this,
1855  duration);
1856 }
1857 
1858 void
1859 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
1860 {
1861  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
1862  /* send a CTS when you receive a RTS
1863  * right after SIFS.
1864  */
1865  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
1866  WifiMacHeader cts;
1867  cts.SetType (WIFI_MAC_CTL_CTS);
1868  cts.SetDsNotFrom ();
1869  cts.SetDsNotTo ();
1870  cts.SetNoMoreFragments ();
1871  cts.SetNoRetry ();
1872  cts.SetAddr1 (source);
1873  duration -= GetCtsDuration (source, rtsTxVector);
1874  duration -= GetSifs ();
1875  NS_ASSERT (duration.IsPositive ());
1876  cts.SetDuration (duration);
1877 
1878  Ptr<Packet> packet = Create<Packet> ();
1879  packet->AddHeader (cts);
1880  AddWifiMacTrailer (packet);
1881 
1882  SnrTag tag;
1883  tag.Set (rtsSnr);
1884  packet->AddPacketTag (tag);
1885 
1886  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1887  ForwardDown (packet, &cts, ctsTxVector);
1888 }
1889 
1890 void
1892 {
1893  NS_LOG_FUNCTION (this);
1894  /* send the third step in a
1895  * RTS/CTS/DATA/ACK handshake
1896  */
1897  NS_ASSERT (m_currentPacket != 0);
1898 
1899  if (m_currentHdr.IsQosData ())
1900  {
1901  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1902  if (!m_aggregateQueue[GetTid (m_currentPacket, m_currentHdr)]->IsEmpty ())
1903  {
1904  for (std::vector<Item>::size_type i = 0; i != m_txPackets[tid].size (); i++)
1905  {
1906  AcIndex ac = QosUtilsMapTidToAc (tid);
1907  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
1908  edcaIt->second->CompleteMpduTx (m_txPackets[tid].at (i).packet, m_txPackets[tid].at (i).hdr, m_txPackets[tid].at (i).timestamp);
1909  }
1910  }
1911  }
1912 
1914  Time newDuration = Seconds (0);
1916  {
1917  newDuration += GetSifs ();
1919  newDuration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1920  }
1922  {
1923  newDuration += GetSifs ();
1925  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1926  }
1927  else if (m_txParams.MustWaitNormalAck ())
1928  {
1929  newDuration += GetSifs ();
1931  }
1932  if (m_txParams.HasNextPacket ())
1933  {
1935  {
1936  newDuration += GetRifs ();
1937  }
1938  else
1939  {
1940  newDuration += GetSifs ();
1941  }
1944  {
1945  newDuration += GetSifs ();
1947  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1948  }
1949  else if (m_txParams.MustWaitNormalAck ())
1950  {
1951  newDuration += GetSifs ();
1953  }
1954  }
1955 
1957  duration -= txDuration;
1958  duration -= GetSifs ();
1959 
1960  duration = std::max (duration, newDuration);
1961  NS_ASSERT (duration.IsPositive ());
1962  m_currentHdr.SetDuration (duration);
1963  Ptr <Packet> packet = m_currentPacket->Copy ();
1964  if (m_ampdu)
1965  {
1967  }
1968  else
1969  {
1970  packet->AddHeader (m_currentHdr);
1971  AddWifiMacTrailer (packet);
1972  }
1974 }
1975 
1976 void
1978 {
1979  NS_LOG_FUNCTION (this);
1981 }
1982 
1983 void
1985 {
1986  NS_LOG_FUNCTION (this);
1988 }
1989 
1990 void
1992 {
1993  NS_LOG_FUNCTION (this);
1995  {
1997  }
1998  if (!m_cfAckInfo.expectCfAck)
1999  {
2000  Ptr<Txop> txop = m_currentTxop;
2001  txop->EndTxNoAck ();
2002  }
2003  if (!IsCfPeriod ())
2004  {
2005  m_currentTxop = 0;
2006  }
2007 }
2008 
2009 void
2010 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2011 {
2012  NS_LOG_FUNCTION (this);
2013  // send an ACK, after SIFS, when you receive a packet
2014  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2015  WifiMacHeader ack;
2016  ack.SetType (WIFI_MAC_CTL_ACK);
2017  ack.SetDsNotFrom ();
2018  ack.SetDsNotTo ();
2019  ack.SetNoRetry ();
2020  ack.SetNoMoreFragments ();
2021  ack.SetAddr1 (source);
2022  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2023  // minus the time to transmit the ACK frame and its SIFS interval
2024  duration -= GetAckDuration (ackTxVector);
2025  duration -= GetSifs ();
2026  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
2027  ack.SetDuration (duration);
2028 
2029  Ptr<Packet> packet = Create<Packet> ();
2030  packet->AddHeader (ack);
2031  AddWifiMacTrailer (packet);
2032 
2033  SnrTag tag;
2034  tag.Set (dataSnr);
2035  packet->AddPacketTag (tag);
2036 
2037  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2038  ForwardDown (packet, &ack, ackTxVector);
2039 }
2040 
2041 bool
2043 {
2047  {
2048  Mac48Address originator = hdr.GetAddr2 ();
2049  uint8_t tid = 0;
2050  if (hdr.IsQosData ())
2051  {
2052  tid = hdr.GetQosTid ();
2053  }
2054  uint16_t seqNumber = hdr.GetSequenceNumber ();
2055  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2056  if (it != m_bAckAgreements.end ())
2057  {
2058  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2059  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2060  {
2061  StoreMpduIfNeeded (packet, hdr);
2062  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2063  {
2064  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2065  if (delta > 1)
2066  {
2067  (*it).second.first.SetWinEnd (seqNumber);
2068  int16_t winEnd = (*it).second.first.GetWinEnd ();
2069  int16_t bufferSize = (*it).second.first.GetBufferSize ();
2070  uint16_t sum = (static_cast<uint16_t> (std::abs (winEnd - bufferSize + 1))) % 4096;
2071  (*it).second.first.SetStartingSequence (sum);
2072  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2073  }
2074  }
2075  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2076  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2077  }
2078  return true;
2079  }
2080  return false;
2081  }
2082  return StoreMpduIfNeeded (packet, hdr);
2083 }
2084 
2085 bool
2087 {
2088  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2089  if (it != m_bAckAgreements.end ())
2090  {
2091  WifiMacTrailer fcs;
2092  packet->RemoveTrailer (fcs);
2093  BufferedPacket bufferedPacket (packet, hdr);
2094 
2095  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2096  uint32_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2097 
2098  BufferedPacketI i = (*it).second.second.begin ();
2099  for (; i != (*it).second.second.end ()
2100  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2101  {
2102  }
2103  (*it).second.second.insert (i, bufferedPacket);
2104 
2105  //Update block ack cache
2106  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2107  NS_ASSERT (j != m_bAckCaches.end ());
2108  (*j).second.UpdateWithMpdu (&hdr);
2109  return true;
2110  }
2111  return false;
2112 }
2113 
2114 void
2116  uint16_t startingSeq)
2117 {
2118  NS_LOG_FUNCTION (this);
2119  uint8_t tid = respHdr->GetTid ();
2120  BlockAckAgreement agreement (originator, tid);
2121  if (respHdr->IsImmediateBlockAck ())
2122  {
2123  agreement.SetImmediateBlockAck ();
2124  }
2125  else
2126  {
2127  agreement.SetDelayedBlockAck ();
2128  }
2129  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2130  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2131  agreement.SetTimeout (respHdr->GetTimeout ());
2132  agreement.SetStartingSequence (startingSeq);
2133 
2134  std::list<BufferedPacket> buffer (0);
2135  AgreementKey key (originator, respHdr->GetTid ());
2136  AgreementValue value (agreement, buffer);
2137  m_bAckAgreements.insert (std::make_pair (key, value));
2138 
2139  BlockAckCache cache;
2140  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2141  m_bAckCaches.insert (std::make_pair (key, cache));
2142 
2143  if (respHdr->GetTimeout () != 0)
2144  {
2145  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2146  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2147 
2148  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2149 
2150  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2152  m_edca[ac], originator, tid, false);
2153  }
2154 }
2155 
2156 void
2158 {
2159  NS_LOG_FUNCTION (this);
2160  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2161  if (it != m_bAckAgreements.end ())
2162  {
2163  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2164  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2165  m_bAckAgreements.erase (it);
2166  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2167  NS_ASSERT (i != m_bAckCaches.end ());
2168  m_bAckCaches.erase (i);
2169  }
2170 }
2171 
2172 void
2174 {
2175  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2176  if (it != m_bAckAgreements.end ())
2177  {
2178  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2179  uint32_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2180  BufferedPacketI last = (*it).second.second.begin ();
2181  uint16_t guard = 0;
2182  if (last != (*it).second.second.end ())
2183  {
2184  guard = (*it).second.second.begin ()->second.GetSequenceControl ();
2185  }
2186  BufferedPacketI i = (*it).second.second.begin ();
2187  for (; i != (*it).second.second.end ()
2188  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedStart; )
2189  {
2190  if (guard == (*i).second.GetSequenceControl ())
2191  {
2192  if (!(*i).second.IsMoreFragments ())
2193  {
2194  while (last != i)
2195  {
2196  m_rxCallback ((*last).first, &(*last).second);
2197  last++;
2198  }
2199  m_rxCallback ((*last).first, &(*last).second);
2200  last++;
2201  /* go to next packet */
2202  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2203  {
2204  i++;
2205  }
2206  if (i != (*it).second.second.end ())
2207  {
2208  guard = (*i).second.GetSequenceControl ();
2209  last = i;
2210  }
2211  }
2212  else
2213  {
2214  guard++;
2215  }
2216  }
2217  else
2218  {
2219  /* go to next packet */
2220  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2221  {
2222  i++;
2223  }
2224  if (i != (*it).second.second.end ())
2225  {
2226  guard = (*i).second.GetSequenceControl ();
2227  last = i;
2228  }
2229  }
2230  }
2231  (*it).second.second.erase ((*it).second.second.begin (), i);
2232  }
2233 }
2234 
2235 void
2237 {
2238  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2239  if (it != m_bAckAgreements.end ())
2240  {
2241  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2242  BufferedPacketI lastComplete = (*it).second.second.begin ();
2243  BufferedPacketI i = (*it).second.second.begin ();
2244  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2245  {
2246  if (!(*i).second.IsMoreFragments ())
2247  {
2248  while (lastComplete != i)
2249  {
2250  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2251  lastComplete++;
2252  }
2253  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2254  lastComplete++;
2255  }
2256  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2257  }
2258  (*it).second.first.SetStartingSequenceControl (guard);
2259  /* All packets already forwarded to WifiMac must be removed from buffer:
2260  [begin (), lastComplete) */
2261  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2262  }
2263 }
2264 void
2265 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2266  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2267 {
2268  NS_LOG_FUNCTION (this);
2269  Ptr<Packet> packet = Create<Packet> ();
2270  packet->AddHeader (*blockAck);
2271 
2272  WifiMacHeader hdr;
2274  hdr.SetAddr1 (originator);
2275  hdr.SetAddr2 (GetAddress ());
2276  hdr.SetDsNotFrom ();
2277  hdr.SetDsNotTo ();
2278  hdr.SetNoRetry ();
2279  hdr.SetNoMoreFragments ();
2280 
2281  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2282 
2283  if (immediate)
2284  {
2286  duration -= GetSifs ();
2287  if (blockAck->IsBasic ())
2288  {
2289  duration -= GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
2290  }
2291  else if (blockAck->IsCompressed ())
2292  {
2293  duration -= GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2294  }
2295  else if (blockAck->IsMultiTid ())
2296  {
2297  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2298  }
2299  }
2300  else
2301  {
2302  m_txParams.EnableAck ();
2303  duration += GetSifs ();
2304  duration += GetAckDuration (originator, blockAckReqTxVector);
2305  }
2307 
2308  if (!immediate)
2309  {
2310  StartDataTxTimers (blockAckReqTxVector);
2311  }
2312 
2313  NS_ASSERT (duration.IsPositive ());
2314  hdr.SetDuration (duration);
2315  //here should be present a control about immediate or delayed block ack
2316  //for now we assume immediate
2317  packet->AddHeader (hdr);
2318  AddWifiMacTrailer (packet);
2319  SnrTag tag;
2320  tag.Set (rxSnr);
2321  packet->AddPacketTag (tag);
2322  ForwardDown (packet, &hdr, blockAckReqTxVector);
2323 }
2324 
2325 void
2326 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2327 {
2328  NS_LOG_FUNCTION (this);
2329  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2330  {
2331  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2332  CtrlBAckResponseHeader blockAck;
2333  uint16_t seqNumber = 0;
2334  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2335  NS_ASSERT (i != m_bAckCaches.end ());
2336  seqNumber = (*i).second.GetWinStart ();
2337 
2338  bool immediate = true;
2339  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2340  blockAck.SetStartingSequence (seqNumber);
2341  blockAck.SetTidInfo (tid);
2342  immediate = (*it).second.first.IsImmediateBlockAck ();
2343  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2344  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2345  (*i).second.FillBlockAckBitmap (&blockAck);
2346 
2347  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode (), rxSnr);
2348  }
2349  else
2350  {
2351  NS_LOG_DEBUG ("Skip block ack response!");
2352  }
2353 }
2354 
2355 void
2357  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2358 {
2359  NS_LOG_FUNCTION (this);
2360  CtrlBAckResponseHeader blockAck;
2361  uint8_t tid = 0;
2362  bool immediate = false;
2363  if (!reqHdr.IsMultiTid ())
2364  {
2365  tid = reqHdr.GetTidInfo ();
2366  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2367  if (it != m_bAckAgreements.end ())
2368  {
2369  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2370  blockAck.SetTidInfo (tid);
2371  immediate = (*it).second.first.IsImmediateBlockAck ();
2372  if (reqHdr.IsBasic ())
2373  {
2374  blockAck.SetType (BASIC_BLOCK_ACK);
2375  }
2376  else if (reqHdr.IsCompressed ())
2377  {
2378  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2379  }
2380  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2381  NS_ASSERT (i != m_bAckCaches.end ());
2382  (*i).second.FillBlockAckBitmap (&blockAck);
2383  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2384 
2388  {
2389  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2390  * See 9.10.3 in IEEE 802.11e standard.
2391  */
2393  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2394  }
2395  else
2396  {
2397  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2398  {
2399  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2400  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2402  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2403  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2404  }
2405  }
2406  }
2407  else
2408  {
2409  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2410  }
2411  }
2412  else
2413  {
2414  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2415  }
2416  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2417 }
2418 
2419 void
2421 {
2422  if (agreement.GetTimeout () != 0)
2423  {
2424  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2425  agreement.m_inactivityEvent.Cancel ();
2426  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2427  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2430  m_edca[ac], agreement.GetPeer (),
2431  agreement.GetTid (), false);
2432  }
2433 }
2434 
2435 void
2437 {
2438  m_edca.insert (std::make_pair (ac, edca));
2439 }
2440 
2441 void
2442 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector)
2443 {
2444  NS_LOG_FUNCTION (this);
2445  AmpduTag ampdu;
2446  bool normalAck = false;
2447  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2448  if (aggregatedPacket->RemovePacketTag (ampdu))
2449  {
2450  ampduSubframe = true;
2452  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2453 
2454  WifiMacHeader firsthdr;
2455  (*n).first->PeekHeader (firsthdr);
2456  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2457  NotifyNav ((*n).first, firsthdr);
2458 
2459  if (firsthdr.GetAddr1 () == m_self)
2460  {
2461  bool singleMpdu = (*n).second.GetEof ();
2462  if (singleMpdu)
2463  {
2464  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2465  NS_LOG_DEBUG ("Receive S-MPDU");
2466  ampduSubframe = false;
2467  }
2468  else if (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE || !m_sendAckEvent.IsRunning ())
2469  {
2472  firsthdr.GetQosTid (),
2473  firsthdr.GetAddr2 (),
2474  firsthdr.GetDuration (),
2475  txVector,
2476  rxSnr);
2477  }
2478 
2479  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2480  {
2481  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2482  }
2483  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2484  {
2485  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2486  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2487  if (firsthdr.IsQosAck ())
2488  {
2489  NS_LOG_DEBUG ("Normal Ack");
2490  normalAck = true;
2491  }
2492  }
2493  else
2494  {
2495  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2496  }
2497 
2498  if (ampdu.GetRemainingNbOfMpdus () == 0 && !singleMpdu)
2499  {
2500  if (normalAck)
2501  {
2502  //send block Ack
2503  if (firsthdr.IsBlockAckReq ())
2504  {
2505  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2506  }
2507  uint8_t tid = firsthdr.GetQosTid ();
2508  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2509  if (it != m_bAckAgreements.end ())
2510  {
2511  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2512  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2513  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2515  }
2516  else
2517  {
2518  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2519  }
2520  }
2521  }
2522  }
2523  }
2524  else
2525  {
2526  ReceiveOk (aggregatedPacket, rxSnr, txVector, ampduSubframe);
2527  }
2528 }
2529 
2530 bool
2531 MacLow::StopMpduAggregation (Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint8_t blockAckSize) const
2532 {
2533  if (peekedPacket == 0)
2534  {
2535  NS_LOG_DEBUG ("no more packets in queue");
2536  return true;
2537  }
2538 
2539  Time aPPDUMaxTime = MicroSeconds (5484);
2540  uint8_t tid = GetTid (peekedPacket, peekedHdr);
2541  AcIndex ac = QosUtilsMapTidToAc (tid);
2542  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2543 
2544  if (m_phy->GetGreenfield ())
2545  {
2546  aPPDUMaxTime = MicroSeconds (10000);
2547  }
2548 
2549  //A STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime
2550  if (m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, m_currentTxVector, m_phy->GetFrequency ()) > aPPDUMaxTime)
2551  {
2552  NS_LOG_DEBUG ("no more packets can be aggregated to satisfy PPDU <= aPPDUMaxTime");
2553  return true;
2554  }
2555 
2556  if (!edcaIt->second->GetMpduAggregator ()->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, blockAckSize))
2557  {
2558  NS_LOG_DEBUG ("no more packets can be aggregated because the maximum A-MPDU size has been reached");
2559  return true;
2560  }
2561 
2562  return false;
2563 }
2564 
2567 {
2568  bool isAmpdu = false;
2569  Ptr<Packet> newPacket, tempPacket;
2570  WifiMacHeader peekedHdr;
2571  newPacket = packet->Copy ();
2572  Ptr<Packet> currentAggregatedPacket;
2573  CtrlBAckRequestHeader blockAckReq;
2574 
2575  if (hdr.IsBlockAckReq ())
2576  {
2577  //Workaround to avoid BlockAckReq to be part of an A-MPDU. The standard says that
2578  //BlockAckReq is not present in A-MPDU if any QoS data frames for that TID are present.
2579  //Since an A-MPDU in non-PSMP frame exchanges aggregates MPDUs from one TID, this means
2580  //we should stop aggregation here for single-TID A-MPDUs. Once PSMP and multi-TID A-MPDUs
2581  //are supported, the condition of entering here should be changed.
2582  return newPacket;
2583  }
2584 
2585  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2586  if (hdr.IsQosData () || hdr.IsBlockAck ()|| hdr.IsBlockAckReq ())
2587  {
2588  Time tstamp;
2589  uint8_t tid = GetTid (packet, hdr);
2590  Ptr<WifiMacQueue> queue;
2591  Ptr<Packet> aggPacket;
2592  AcIndex ac = QosUtilsMapTidToAc (tid);
2593  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2594  NS_ASSERT (edcaIt != m_edca.end ());
2595  queue = edcaIt->second->GetWifiMacQueue ();
2596 
2597  if (!hdr.GetAddr1 ().IsBroadcast () && edcaIt->second->GetMpduAggregator () != 0)
2598  {
2599  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2600  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2601  {
2602  /* here is performed mpdu aggregation */
2603  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2604  currentAggregatedPacket = Create<Packet> ();
2605  peekedHdr = hdr;
2606  uint16_t startingSequenceNumber = 0;
2607  uint16_t currentSequenceNumber = 0;
2608  uint8_t qosPolicy = 0;
2609  uint8_t blockAckSize = 0;
2610  bool aggregated = false;
2611  uint8_t i = 0;
2612  aggPacket = newPacket->Copy ();
2613 
2614  if (!hdr.IsBlockAckReq ())
2615  {
2616  if (!hdr.IsBlockAck ())
2617  {
2618  startingSequenceNumber = peekedHdr.GetSequenceNumber ();
2619  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2620  }
2621  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2622  newPacket->AddHeader (peekedHdr);
2623  AddWifiMacTrailer (newPacket);
2624 
2625  aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2626 
2627  if (aggregated)
2628  {
2629  NS_LOG_DEBUG ("Adding packet with sequence number " << currentSequenceNumber << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2630  i++;
2631  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2632  }
2633  }
2634  else if (hdr.IsBlockAckReq ())
2635  {
2636  blockAckSize = static_cast<uint8_t> (packet->GetSize () + hdr.GetSize () + WIFI_MAC_FCS_LENGTH);
2637  qosPolicy = 3; //if the last subframe is block ack req then set ack policy of all frames to blockack
2638  packet->PeekHeader (blockAckReq);
2639  startingSequenceNumber = blockAckReq.GetStartingSequence ();
2640  }
2642  bool retry = false;
2643  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
2644  Ptr<const Packet> peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, tid, &tstamp);
2645  if (peekedPacket == 0)
2646  {
2647  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,
2746  hdr.GetAddr1 ());
2747  if (item != 0)
2748  {
2749  peekedPacket = item->GetPacket ();
2750  peekedHdr = item->GetHeader ();
2751  tstamp = item->GetTimeStamp ();
2752  //find what will the sequence number be so that we don't send more than 64 packets apart
2753  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2754 
2755  if (edcaIt->second->GetMsduAggregator () != 0)
2756  {
2757  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2758  if (tempPacket != 0) //MSDU aggregation
2759  {
2760  peekedPacket = tempPacket->Copy ();
2761  }
2762  }
2763  }
2764  }
2765  else
2766  {
2767  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2768  }
2769  }
2770  else
2771  {
2772  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2773  hdr.GetAddr1 ());
2774  if (item != 0)
2775  {
2776  peekedPacket = item->GetPacket ();
2777  peekedHdr = item->GetHeader ();
2778  tstamp = item->GetTimeStamp ();
2779  //find what will the sequence number be so that we don't send more than 64 packets apart
2780  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2781 
2782  if (edcaIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
2783  {
2784  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2785  if (tempPacket != 0) //MSDU aggregation
2786  {
2787  peekedPacket = tempPacket->Copy ();
2788  }
2789  }
2790  }
2791  else
2792  {
2793  peekedPacket = 0;
2794  }
2795  }
2796  }
2797 
2798  if (isAmpdu)
2799  {
2800  if (hdr.IsBlockAckReq ())
2801  {
2802  newPacket = packet->Copy ();
2803  peekedHdr = hdr;
2804  aggPacket = newPacket->Copy ();
2805  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2806  newPacket->AddHeader (peekedHdr);
2807  AddWifiMacTrailer (newPacket);
2808  edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2809  currentAggregatedPacket->AddHeader (blockAckReq);
2810  }
2811 
2812  if (qosPolicy == 0)
2813  {
2814  edcaIt->second->CompleteAmpduTransfer (hdr.GetAddr1 (), tid);
2815  }
2816 
2817  //Add packet tag
2818  AmpduTag ampdutag;
2819  ampdutag.SetRemainingNbOfMpdus (i - 1);
2820  newPacket = currentAggregatedPacket;
2821  newPacket->AddPacketTag (ampdutag);
2822 
2823  NS_LOG_DEBUG ("tx unicast A-MPDU");
2824  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2825  }
2826  else
2827  {
2828  uint32_t queueSize = m_aggregateQueue[tid]->GetNPackets ();
2829  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
2830  if (queueSize >= 1)
2831  {
2832  //remove any packets that we added to the aggregate queue
2833  FlushAggregateQueue (tid);
2834  }
2835  }
2836  }
2837  // VHT/HE single MPDU operation
2839  if (!isAmpdu
2840  && hdr.IsQosData ()
2841  && (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT
2842  || dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HE))
2843  {
2844  peekedHdr = hdr;
2846 
2847  currentAggregatedPacket = Create<Packet> ();
2848  edcaIt->second->GetMpduAggregator ()->AggregateSingleMpdu (packet, currentAggregatedPacket);
2849  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (packet, peekedHdr));
2850  if (m_txParams.MustSendRts ())
2851  {
2852  InsertInTxQueue (packet, peekedHdr, tstamp, tid);
2853  }
2854  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2855  {
2856  edcaIt->second->CompleteAmpduTransfer (peekedHdr.GetAddr1 (), tid);
2857  }
2858 
2859  //Add packet tag
2860  AmpduTag ampdutag;
2861  newPacket = currentAggregatedPacket;
2862  newPacket->AddHeader (peekedHdr);
2863  AddWifiMacTrailer (newPacket);
2864  newPacket->AddPacketTag (ampdutag);
2865 
2866  NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ());
2867  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2868  }
2869  }
2870  }
2871  return newPacket;
2872 }
2873 
2874 void
2876 {
2877  if (!m_aggregateQueue[tid]->IsEmpty ())
2878  {
2879  NS_LOG_DEBUG ("Flush aggregate queue");
2880  m_aggregateQueue[tid]->Flush ();
2881  }
2882  m_txPackets[tid].clear ();
2883 }
2884 
2885 void
2886 MacLow::InsertInTxQueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
2887 {
2888  NS_LOG_FUNCTION (this);
2889  Item item;
2890  item.packet = packet;
2891  item.hdr = hdr;
2892  item.timestamp = tStamp;
2893  m_txPackets[tid].push_back (item);
2894 }
2895 
2897 MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint8_t blockAckSize)
2898 {
2899  bool msduAggregation = false;
2900  bool isAmsdu = false;
2901  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
2902  Ptr<Packet> tempPacket = Create<Packet> ();
2903 
2904  Ptr<WifiMacQueue> queue;
2905  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
2906  std::map<AcIndex, Ptr<QosTxop> >::const_iterator edcaIt = m_edca.find (ac);
2907  NS_ASSERT (edcaIt != m_edca.end ());
2908  queue = edcaIt->second->GetWifiMacQueue ();
2909 
2910  Ptr<const WifiMacQueueItem> peekedItem = queue->DequeueByTidAndAddress (hdr->GetQosTid (),
2911  hdr->GetAddr1 ());
2912  if (peekedItem)
2913  {
2914  *hdr = peekedItem->GetHeader ();
2915  }
2916 
2917  edcaIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
2918  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2919  edcaIt->second->MapDestAddressForAggregation (*hdr));
2920 
2921  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), hdr->GetAddr1 ());
2922  while (peekedItem != 0)
2923  {
2924  *hdr = peekedItem->GetHeader ();
2925  *tstamp = peekedItem->GetTimeStamp ();
2926  tempPacket = currentAmsduPacket;
2927 
2928  msduAggregation = edcaIt->second->GetMsduAggregator ()->Aggregate (peekedItem->GetPacket (), tempPacket,
2929  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2930  edcaIt->second->MapDestAddressForAggregation (*hdr));
2931 
2932  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
2933  {
2934  isAmsdu = true;
2935  currentAmsduPacket = tempPacket;
2936  queue->Remove (peekedItem->GetPacket ());
2937  }
2938  else
2939  {
2940  break;
2941  }
2942  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), hdr->GetAddr1 ());
2943  }
2944 
2945  if (isAmsdu)
2946  {
2947  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
2948  hdr->SetQosAmsdu ();
2949  hdr->SetAddr3 (GetBssid ());
2950  return currentAmsduPacket;
2951  }
2952  else
2953  {
2954  queue->PushFront (Create<WifiMacQueueItem> (packet, *hdr));
2955  return 0;
2956  }
2957 }
2958 
2959 Time
2961 {
2962  NS_LOG_FUNCTION (this);
2964  NS_ASSERT (remainingCfpDuration.IsPositive ());
2965  return remainingCfpDuration;
2966 }
2967 
2968 bool
2970 {
2972 }
2973 
2974 bool
2976 {
2977  NS_LOG_FUNCTION (this);
2978  if (!IsCfPeriod ())
2979  {
2980  return false;
2981  }
2982  NS_ASSERT (GetRemainingCfpDuration ().IsPositive ());
2983  WifiMacHeader hdr;
2984  hdr.SetType (WIFI_MAC_DATA);
2985  WifiMacTrailer fcs;
2986  uint32_t maxMacFrameSize = MAX_MSDU_SIZE + hdr.GetSerializedSize () + fcs.GetSerializedSize ();
2988  return ((GetRemainingCfpDuration () - nextTransmission).IsPositive ());
2989 }
2990 
2991 } //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:1984
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
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 GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:407
bool IsCfEnd(void) const
Return true if the header is a CF-END header.
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:915
bool IsStateOff(void) const
Definition: wifi-phy.cc:3565
bool GetRifsPermitted(void) const
Return whether the device can use RIFS.
uint16_t GetTimeout(void) const
Return the timeout.
bool IsBroadcast(void) const
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
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::vector< Ptr< ChannelAccessManager > >::const_iterator ChannelAccessManagersCI
typedef for an iterator for a list of ChannelAccessManager.
Definition: mac-low.h:889
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:2420
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:897
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1181
Callback template class.
Definition: callback.h:1176
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:959
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:2356
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
void SetPromisc(void)
Enable promiscuous mode.
Definition: mac-low.cc:364
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:139
#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:816
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:717
void NotifyMaybeCcaBusyStart(Time duration)
Definition: mac-low.cc:80
bool GetGreenfield(void) const
Return whether Greenfield is supported.
Definition: wifi-phy.cc:604
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:688
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:117
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:918
void SetPhy(const Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:250
bool StopMpduAggregation(Ptr< const Packet > peekedPacket, WifiMacHeader peekedHdr, Ptr< Packet > aggregatedPacket, uint8_t blockAckSize) const
Definition: mac-low.cc:2531
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:146
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1295
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
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 ReportDataOk(Mac48Address address, const WifiMacHeader *header, double ackSnr, WifiMode ackMode, double dataSnr, uint32_t packetSize)
Should be invoked whenever we receive the Ack associated to a data packet we just sent...
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:942
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:420
virtual void MissedAck(void)
Event handler when an ACK is missed.
Definition: txop.cc:620
WifiTxVector GetCtsTxVector(Mac48Address address, WifiMode rtsMode)
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
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
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
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:1784
static DeaggregatedMpdus Deaggregate(Ptr< Packet > aggregatedPacket)
Deaggregates an A-MPDU by removing the A-MPDU subframe header and padding.
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
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:426
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
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:1496
#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
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
void SendPacket(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype=NORMAL_MPDU)
Definition: wifi-phy.cc:2290
virtual void Cancel(void)
Cancel the transmission.
Definition: txop.cc:710
uint32_t GetAckSize(void)
Return the total ACK size (including FCS trailer).
Definition: wifi-utils.cc:87
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:740
bool m_ampdu
Flag if the current transmission involves an A-MPDU.
Definition: mac-low.h:932
bool NeedRts(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, WifiTxVector txVector)
uint16_t GetBufferSize(void) const
Return the buffer size.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
Callback< R > MakeNullCallback(void)
Definition: callback.h:1635
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:388
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:911
ns3::Time timeout
Ptr< Packet > AggregateToAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Definition: mac-low.cc:2566
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool IsCfPoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
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
bool NeedRts(void) const
Check if the current packet should be sent with a RTS protection.
Definition: mac-low.cc:606
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:2442
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
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
Time m_cfpMaxDuration
CFP max duration.
Definition: mac-low.h:922
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
Time CalculateTransmissionTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &parameters) const
Definition: mac-low.cc:1215
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
control how a packet is transmitted.
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
MpduType
The type of an MPDU.
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
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:955
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
phy
Definition: third.py:86
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:952
Time timestamp
the timestamp
Definition: mac-low.h:873
WifiPreamble GetPreambleType(void) const
void RemovePhyMacLowListener(Ptr< WifiPhy > phy)
Remove current WifiPhy listener for this MacLow.
Definition: mac-low.cc:161
uint8_t GetTid(void) const
Return the Traffic ID (TID).
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2236
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:444
void NotifyOn(void)
Notify listeners that we went to switch on.
Definition: mac-low.cc:98
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:960
The MPDU is not part of an A-MPDU.
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2157
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:925
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
void SetCfpMaxDuration(Time duration)
Definition: mac-low.cc:352
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1130
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
std::pair< Ptr< Packet >, WifiMacHeader > BufferedPacket
buffered packet typedef
Definition: mac-low.h:939
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:1790
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:957
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send ACK after receiving DATA.
Definition: mac-low.cc:2010
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1381
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:370
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:2115
bool IsZero(void) const
Definition: nstime.h:288
Time m_lastBeacon
The time when the last beacon frame transmission started.
Definition: mac-low.h:928
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.
bool IsBeacon(void) const
Return true if the header is a Beacon header.
uint16_t GetTimeout(void) const
Return the timeout.
Listener for PHY events.
Definition: mac-low.cc:53
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1038
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.
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:400
void EndTxNoAck(void)
A transmission that does not require an ACK has completed.
Definition: mac-low.cc:1991
uint32_t GetSerializedSize(void) const
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:2326
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
block ack caches iterator typedef
Definition: mac-low.h:949
virtual bool IsCfPeriod(void) const
This function indicates whether it is the CF period.
Definition: mac-low.cc:2969
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:1307
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:31
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:394
bool IsCts(void) const
Return true if the header is a CTS header.
WifiMode GetMode(void) const
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
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Headers for Block ack response.
Definition: ctrl-headers.h:181
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void SendDataAfterCts(Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:1891
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2436
Agreements m_bAckAgreements
block ack agreements
Definition: mac-low.h:951
Ptr< WifiMacQueue > m_aggregateQueue[8]
Queues per TID used for MPDU aggregation.
Definition: mac-low.h:958
void SendMpdu(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype)
Forward the MPDU down to WifiPhy for transmission.
Definition: mac-low.cc:1477
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
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
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:642
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:500
void NotifyOff(void)
Notify listeners that we went to switch off.
Definition: mac-low.cc:91
Time GetCfpMaxDuration(void) const
Definition: mac-low.cc:438
Time m_slotTime
Slot duration.
Definition: mac-low.h:917
bool IsQosAck(void) const
Return if the QoS ACK policy is Normal ACK.
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
Mac48Address GetPeer(void) const
Return the peer address.
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:931
void NotifyRxStart(Time duration)
Definition: mac-low.cc:68
WifiMacHeader hdr
the header
Definition: mac-low.h:872
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:198
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
std::list< BufferedPacket >::iterator BufferedPacketI
buffered packet iterator typedef
Definition: mac-low.h:940
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1537
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.
uint8_t GetRemainingNbOfMpdus(void) const
Definition: ampdu-tag.cc:89
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:376
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.
Time GetRemainingCfpDuration(void) const
Definition: mac-low.cc:2960
void GotCfEnd(void)
Event handler when a CF-END frame is received.
Definition: txop.cc:648
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:388
bool HasHeSupported(void) const
Return whether the device has HE capability support enabled.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
void RegisterDcf(Ptr< ChannelAccessManager > dcf)
Definition: mac-low.cc:456
bool IsData(void) const
Return true if the Type is DATA.
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
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1243
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.
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
virtual void MissedBlockAck(uint8_t nMpdus)
Event handler when a Block ACK timeout has occurred.
Definition: txop.cc:828
bool HasPcfSupported(void) const
Return whether the device has PCF capability support enabled.
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:1614
void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:95
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
void SetType(BlockAckType type)
Set the block ACK type.
Time m_beaconInterval
Expected interval between two beacon transmissions.
Definition: mac-low.h:921
void NotifyCtsTimeoutResetNow()
Notify ChannelAccessManager that CTS timer should be reset.
Definition: mac-low.cc:1340
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:133
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
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
Time m_cfpForeshortening
The delay the current CF period should be foreshortened.
Definition: mac-low.h:929
void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:77
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
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:2265
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the ACK (including preamble and FCS).
Definition: mac-low.cc:1106
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:912
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:98
Time GetRemainingAmpduDuration(void) const
Definition: ampdu-tag.cc:95
void DisableRts(void)
Do not send rts and wait for cts before sending data.
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:2173
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:1859
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:913
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:310
void FlushAggregateQueue(uint8_t tid)
This function is called to flush the aggregate queue, which is used for A-MPDU.
Definition: mac-low.cc:2875
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:916
void SetBeaconInterval(Time interval)
Definition: mac-low.cc:346
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
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:125
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:924
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.
uint16_t GetRawDuration(void) const
Return the raw duration from the Duration/ID field.
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:414
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:901
bool IsStateTx(void) const
Definition: wifi-phy.cc:3547
bool ReceiveMpdu(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:2042
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header, uint32_t packetSize)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
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:909
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)
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.
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:910
Maintains information for a block ack agreement.
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
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:852
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
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
void NotifyAckTimeoutStartNow(Time duration)
Notify ChannelAccessManager that ACK timer should be started for the given duration.
Definition: mac-low.cc:1313
bool CanTransmitNextCfFrame(void) const
This function decides if a CF frame can be transmitted in the current CFP.
Definition: mac-low.cc:2975
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
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
bool IsPositive(void) const
Definition: nstime.h:298
void Reset(void)
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot. ...
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
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
Time m_cfpStart
The time when the latest CF period started.
Definition: mac-low.h:927
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:95
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
agreements iterator
Definition: mac-low.h:946
uint32_t GetSerializedSize(void) const
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:903
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
void MissedCfPollResponse(bool expectedCfAck)
Event handler when a response to a CF-POLL frame is missed.
Definition: txop.cc:662
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
CfAckInfo m_cfAckInfo
Info about piggyback ACKs used in PCF.
Definition: mac-low.h:962
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
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
bool IsRts(void) const
Return true if the header is a RTS header.
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:1673
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1030
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:420
bool IsAck(void) const
Return true if the header is an ACK header.
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
uint32_t GetCfEndSize(void) const
Return the total CF-END size (including FCS trailer).
Definition: mac-low.cc:1084
second
Definition: nstime.h:114
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:1977
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:61
Time GetBeaconInterval(void) const
Definition: mac-low.cc:432
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:2897
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:874
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:914
void CfPollTimeout(void)
Event handler when CF-POLL timeout occurs.
Definition: mac-low.cc:1484
void SetRemainingNbOfMpdus(uint8_t nbofmpdus)
Definition: ampdu-tag.cc:52
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
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
void InsertInTxQueue(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
Insert in a temporary queue.
Definition: mac-low.cc:2886
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:822
void DisableAck(void)
Do not wait for Ack after data transmission.
std::pair< BlockAckAgreement, std::list< BufferedPacket > > AgreementValue
agreement value typedef
Definition: mac-low.h:943
Time GetSlotTime(void) const
Return slot duration of this MacLow.
Definition: mac-low.cc:414
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.
a unique identifier for an interface.
Definition: type-id.h:58
void SetRxCallback(Callback< void, Ptr< Packet >, const WifiMacHeader *> callback)
Definition: mac-low.cc:450
WifiTxVector GetAckTxVector(Mac48Address address, WifiMode dataMode)
BlockAckCache cache.
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool NeedCtsToSelf(void) const
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:614
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
Time GetLastRxStartTime(void) const
Return the start time of the last received packet.
Definition: wifi-phy.cc:3577
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:382
bool IsStateRx(void) const
Definition: wifi-phy.cc:3541
void SetQosAmsdu(void)
Set that A-MSDU is present.
Time m_rifs
Reduced Interframe Space (RIFS) duration.
Definition: mac-low.h:919
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
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
bool StoreMpduIfNeeded(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:2086
virtual bool HasTxop(void) const
Check if the station has TXOP granted for the next MPDU.
Definition: txop.cc:834
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
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:156
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.
void SetCompressedBlockAckTimeout(Time blockAckTimeout)
Set Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:298
Implements the IEEE 802.11 MAC trailer.
Ptr< WifiPhy > GetPhy(void) const
Definition: mac-low.cc:259
class PhyMacLowListener * m_phyMacLowListener
Listener needed to monitor when a channel switching occurs.
Definition: mac-low.h:934
ChannelAccessManagers m_channelAccessManagers
List of ChannelAccessManager.
Definition: mac-low.h:894
bool HasData(void) const
Return true if the header type is DATA and is not DATA_NULL.
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
void SendRtsForPacket(void)
Send RTS to begin RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1552
BlockAckType
The different block ACK policies.
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2236
void SetRemainingAmpduDuration(Time duration)
Definition: ampdu-tag.cc:59
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:290
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.