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