add block ack timeouts
authorMirko Banchi <mk.banchi@gmail.com>
Wed, 03 Feb 2010 20:34:52 +0100
changeset 5958 dd0accd82659
parent 5957 dd5ece55acb9
child 5959 66bc2d3da45f
add block ack timeouts
src/devices/wifi/edca-txop-n.cc
src/devices/wifi/edca-txop-n.h
src/devices/wifi/mac-low.cc
src/devices/wifi/mac-low.h
src/devices/wifi/qadhoc-wifi-mac.cc
src/devices/wifi/qadhoc-wifi-mac.h
src/devices/wifi/qap-wifi-mac.cc
src/devices/wifi/qap-wifi-mac.h
src/devices/wifi/qsta-wifi-mac.cc
src/devices/wifi/qsta-wifi-mac.h
src/devices/wifi/wifi-mac.cc
src/devices/wifi/wifi-mac.h
--- a/src/devices/wifi/edca-txop-n.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -87,6 +87,9 @@
   virtual void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source) {
     m_txop->GotBlockAck (blockAck, source);
   }
+  virtual void MissedBlockAck (void) {
+    m_txop->MissedBlockAck ();
+  }
   virtual void StartNext (void) {
     m_txop->StartNext ();
   }
@@ -507,6 +510,20 @@
   RestartAccessIfNeeded ();
 }
 
+void
+EdcaTxopN::MissedBlockAck (void)
+{
+  NS_LOG_FUNCTION (this);
+  MY_DEBUG ("missed block ack");
+  
+  MY_DEBUG ("Retransmit block ack request");
+  m_currentHdr.SetRetry ();
+  m_dcf->UpdateFailedCw ();
+  
+  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
+  RestartAccessIfNeeded ();
+}
+
 Ptr<MsduAggregator>
 EdcaTxopN::GetMsduAggregator (void) const
 {
--- a/src/devices/wifi/edca-txop-n.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.h	Wed Feb 03 20:34:52 2010 +0100
@@ -114,6 +114,7 @@
   void MissedCts (void);
   void GotAck (double snr, WifiMode txMode);
   void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient);
+  void MissedBlockAck (void);
   void GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address recipient);
   void MissedAck (void);
   void StartNext (void);
--- a/src/devices/wifi/mac-low.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/mac-low.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -117,6 +117,9 @@
 MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck,
                                          Mac48Address source)
 {}
+void
+MacLowTransmissionListener::MissedBlockAck (void)
+{}
 MacLowDcfListener::MacLowDcfListener ()
 {}
 MacLowDcfListener::~MacLowDcfListener ()
@@ -319,6 +322,7 @@
     m_fastAckTimeoutEvent (),
     m_superFastAckTimeoutEvent (),
     m_fastAckFailedTimeoutEvent (),
+    m_blockAckTimeoutEvent (),
     m_ctsTimeoutEvent (),
     m_sendCtsEvent (),
     m_sendAckEvent (),
@@ -353,6 +357,7 @@
   m_fastAckTimeoutEvent.Cancel ();
   m_superFastAckTimeoutEvent.Cancel ();
   m_fastAckFailedTimeoutEvent.Cancel ();
+  m_blockAckTimeoutEvent.Cancel ();
   m_ctsTimeoutEvent.Cancel ();
   m_sendCtsEvent.Cancel ();
   m_sendAckEvent.Cancel ();
@@ -389,6 +394,11 @@
       m_fastAckFailedTimeoutEvent.Cancel ();
       oneRunning = true;
     }
+  if (m_blockAckTimeoutEvent.IsRunning ())
+    {
+      m_blockAckTimeoutEvent.Cancel ();
+      oneRunning = true;
+    }
   if (m_ctsTimeoutEvent.IsRunning ()) 
     {
       m_ctsTimeoutEvent.Cancel ();
@@ -445,6 +455,16 @@
 {
   m_ackTimeout = ackTimeout;
 }
+void
+MacLow::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  m_basicBlockAckTimeout = blockAckTimeout;
+}
+void
+MacLow::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  m_compressedBlockAckTimeout = blockAckTimeout;
+}
 void 
 MacLow::SetCtsTimeout (Time ctsTimeout)
 {
@@ -480,6 +500,16 @@
 {
   return m_ackTimeout;
 }
+Time
+MacLow::GetBasicBlockAckTimeout () const
+{
+  return m_basicBlockAckTimeout;
+}
+Time
+MacLow::GetCompressedBlockAckTimeout () const
+{
+  return m_compressedBlockAckTimeout;
+}
 Time 
 MacLow::GetCtsTimeout (void) const
 {
@@ -696,13 +726,13 @@
         }
     } 
   else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self &&
-          (m_txParams.MustWaitBasicBlockAck () || m_txParams.MustWaitCompressedBlockAck ())) 
-          //m_blockAckTimeoutEvent.IsRunning ())
+          (m_txParams.MustWaitBasicBlockAck () || m_txParams.MustWaitCompressedBlockAck ()) && 
+           m_blockAckTimeoutEvent.IsRunning ())
     {
       NS_LOG_DEBUG ("got block ack from "<<hdr.GetAddr2 ());
       CtrlBAckResponseHeader blockAck;
       packet->RemoveHeader (blockAck);
-      //m_blockAckTimeoutEvent.Cancel ();
+      m_blockAckTimeoutEvent.Cancel ();
       m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 ());
     }
   else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
@@ -868,7 +898,14 @@
 Time
 MacLow::GetBlockAckDuration (Mac48Address to, WifiMode blockAckReqTxMode, enum BlockAckType type) const
 {
-  //WifiMode blockAckMode = GetBlockAckTxModeForBlockAckReq (to, blockAckReqTxMode);
+  /* 
+   * For immediate BlockAck we should transmit the frame with the same WifiMode
+   * as the BlockAckReq.
+   *
+   * from section 9.6 in IEEE802.11e:
+   * The BlockAck control frame shall be sent at the same rate and modulation class as
+   * the BlockAckReq frame if it is sent in response to a BlockAckReq frame.
+   */
   return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxMode, WIFI_PREAMBLE_LONG);
 }
 Time
@@ -1129,6 +1166,18 @@
     }
 }
 void
+MacLow::BlockAckTimeout (void)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_DEBUG ("block ack timeout");
+  
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  station->ReportDataFailed ();
+  MacLowTransmissionListener *listener = m_listener;
+  m_listener = 0;
+  listener->MissedBlockAck ();
+}
+void
 MacLow::SuperFastAckTimeout ()
 {
   NS_LOG_FUNCTION (this);
@@ -1221,7 +1270,19 @@
       NotifyAckTimeoutStartNow (timerDelay);
       m_superFastAckTimeoutEvent = Simulator::Schedule (timerDelay, 
                                                         &MacLow::SuperFastAckTimeout, this);
-    } 
+    }
+  else if (m_txParams.MustWaitBasicBlockAck ())
+    {
+      Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
+      NS_ASSERT (m_blockAckTimeoutEvent.IsExpired ());
+      m_blockAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::BlockAckTimeout, this);
+    }
+  else if (m_txParams.MustWaitCompressedBlockAck ())
+    {
+      Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
+      NS_ASSERT (m_blockAckTimeoutEvent.IsExpired ());
+      m_blockAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::BlockAckTimeout, this);
+    }
   else if (m_txParams.HasNextPacket ()) 
     {
       Time delay = txDuration + GetSifs ();
@@ -1573,9 +1634,6 @@
     {
       m_txParams.DisableAck ();
       duration -= GetSifs ();
-      /* from section 9.6 in IEEE802.11e:
-         The BlockAck control frame shall be sent at the same rate and modulation class as
-         the BlockAckReq frame if it is sent in response to a BlockAckReq frame.*/
       if (blockAck->IsBasic ())
         {
           duration -= GetBlockAckDuration (originator, blockAckReqTxMode, BASIC_BLOCK_ACK);
--- a/src/devices/wifi/mac-low.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/mac-low.h	Wed Feb 03 20:34:52 2010 +0100
@@ -95,6 +95,16 @@
    */
   virtual void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source);
   /**
+   * ns3::MacLow did not receive an expected BLOCK_ACK within
+   * BlockAckTimeout. This method is used only for immediate 
+   * block ack variant. With delayed block ack, the MissedAck method will be
+   * called instead: upon receipt of a block ack request, the rx station will
+   * reply with a normal ack frame. Later, when the rx station gets a txop, it
+   * will send the block ack back to the tx station which will reply with a
+   * normal ack to the rx station.
+   */
+  virtual void MissedBlockAck (void);
+  /**
    * Invoked when ns3::MacLow wants to start a new transmission
    * as configured by MacLowTransmissionParameters::EnableNextData.
    * The listener is expected to call again MacLow::StartTransmission
@@ -338,6 +348,8 @@
 
   void SetAddress (Mac48Address ad);
   void SetAckTimeout (Time ackTimeout);
+  void SetBasicBlockAckTimeout (Time blockAckTimeout);
+  void SetCompressedBlockAckTimeout (Time blockAckTimeout);
   void SetCtsTimeout (Time ctsTimeout);
   void SetSifs (Time sifs);
   void SetSlotTime (Time slotTime);
@@ -345,6 +357,8 @@
   void SetBssid (Mac48Address ad);
   Mac48Address GetAddress (void) const;
   Time GetAckTimeout (void) const;
+  Time GetBasicBlockAckTimeout () const;
+  Time GetCompressedBlockAckTimeout () const;
   Time GetCtsTimeout (void) const;
   Time GetSifs (void) const;
   Time GetSlotTime (void) const;
@@ -474,6 +488,7 @@
   void FastAckTimeout (void);
   void SuperFastAckTimeout (void);
   void FastAckFailedTimeout (void);
+  void BlockAckTimeout (void);
   void CtsTimeout (void);
   void SendCtsAfterRts (Mac48Address source, Time duration, WifiMode txMode, double rtsSnr);
   void SendAckAfterData (Mac48Address source, Time duration, WifiMode txMode, double rtsSnr);
@@ -539,6 +554,7 @@
   EventId m_fastAckTimeoutEvent;
   EventId m_superFastAckTimeoutEvent;
   EventId m_fastAckFailedTimeoutEvent;
+  EventId m_blockAckTimeoutEvent;
   EventId m_ctsTimeoutEvent;
   EventId m_sendCtsEvent;
   EventId m_sendAckEvent;
@@ -553,6 +569,8 @@
   Mac48Address m_self;
   Mac48Address m_bssid;
   Time m_ackTimeout;
+  Time m_basicBlockAckTimeout;
+  Time m_compressedBlockAckTimeout;
   Time m_ctsTimeout;
   Time m_sifs;
   Time m_slotTime;
--- a/src/devices/wifi/qadhoc-wifi-mac.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qadhoc-wifi-mac.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -147,6 +147,18 @@
   m_low->SetAckTimeout (ackTimeout);
 }
 
+void 
+QadhocWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetBasicBlockAckTimeout (blockAckTimeout);
+}
+
+void 
+QadhocWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetCompressedBlockAckTimeout (blockAckTimeout);
+}
+
 void
 QadhocWifiMac::SetCtsTimeout (Time ctsTimeout)
 {
@@ -183,6 +195,18 @@
   return m_low->GetAckTimeout ();
 }
 
+Time 
+QadhocWifiMac::GetBasicBlockAckTimeout (void) const
+{
+  return m_low->GetBasicBlockAckTimeout ();
+}
+
+Time 
+QadhocWifiMac::GetCompressedBlockAckTimeout (void) const
+{
+  return m_low->GetCompressedBlockAckTimeout ();
+}
+
 Time
 QadhocWifiMac::GetCtsTimeout (void) const
 {
--- a/src/devices/wifi/qadhoc-wifi-mac.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qadhoc-wifi-mac.h	Wed Feb 03 20:34:52 2010 +0100
@@ -74,6 +74,10 @@
   virtual void SetAddress (Mac48Address address);
   virtual void SetSsid (Ssid ssid);
   virtual Mac48Address GetBssid (void) const;
+  virtual void SetBasicBlockAckTimeout (Time blockAckTimeout);
+  virtual void SetCompressedBlockAckTimeout (Time blockAckTimeout);
+  virtual Time GetBasicBlockAckTimeout (void) const;
+  virtual Time GetCompressedBlockAckTimeout (void) const;
 
 
 private:
--- a/src/devices/wifi/qap-wifi-mac.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qap-wifi-mac.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -198,6 +198,18 @@
 }
 
 void 
+QapWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetBasicBlockAckTimeout (blockAckTimeout);
+}
+
+void
+QapWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetCompressedBlockAckTimeout (blockAckTimeout);
+}
+
+void 
 QapWifiMac::SetCtsTimeout (Time ctsTimeout)
 {
   m_low->SetCtsTimeout (ctsTimeout);
@@ -234,6 +246,18 @@
 }
 
 Time 
+QapWifiMac::GetBasicBlockAckTimeout () const
+{
+  return m_low->GetBasicBlockAckTimeout ();
+}
+
+Time 
+QapWifiMac::GetCompressedBlockAckTimeout () const
+{
+  return m_low->GetCompressedBlockAckTimeout ();
+}
+
+Time 
 QapWifiMac::GetCtsTimeout (void) const
 {
   return m_low->GetCtsTimeout ();
--- a/src/devices/wifi/qap-wifi-mac.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qap-wifi-mac.h	Wed Feb 03 20:34:52 2010 +0100
@@ -82,6 +82,10 @@
   virtual void SetAddress (Mac48Address address);
   virtual void SetSsid (Ssid ssid);
   virtual Mac48Address GetBssid (void) const;
+  virtual void SetBasicBlockAckTimeout (Time blockAckTimeout);
+  virtual void SetCompressedBlockAckTimeout (Time blockAckTimeout);
+  virtual Time GetBasicBlockAckTimeout (void) const;
+  virtual Time GetCompressedBlockAckTimeout (void) const;
 
   void SetBeaconInterval (Time interval);
   Time GetBeaconInterval (void) const;
--- a/src/devices/wifi/qsta-wifi-mac.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -169,6 +169,18 @@
   m_low->SetAckTimeout (ackTimeout);
 }
 
+void 
+QstaWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetBasicBlockAckTimeout (blockAckTimeout);
+}
+
+void 
+QstaWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  m_low->SetCompressedBlockAckTimeout (blockAckTimeout);
+}
+
 void
 QstaWifiMac::SetCtsTimeout (Time ctsTimeout)
 {
@@ -205,6 +217,18 @@
  return m_low->GetAckTimeout ();
 }
 
+Time 
+QstaWifiMac::GetBasicBlockAckTimeout (void) const
+{
+  return m_low->GetBasicBlockAckTimeout ();
+}
+
+Time 
+QstaWifiMac::GetCompressedBlockAckTimeout (void) const
+{
+  return m_low->GetCompressedBlockAckTimeout ();
+}
+
 Time
 QstaWifiMac::GetCtsTimeout (void) const
 {
--- a/src/devices/wifi/qsta-wifi-mac.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.h	Wed Feb 03 20:34:52 2010 +0100
@@ -81,6 +81,10 @@
   virtual void SetAddress (Mac48Address address);
   virtual void SetSsid (Ssid ssid);
   virtual Mac48Address GetBssid (void) const;
+  virtual void SetBasicBlockAckTimeout (Time blockAckTimeout);
+  virtual void SetCompressedBlockAckTimeout (Time blockAckTimeout);
+  virtual Time GetBasicBlockAckTimeout (void) const;
+  virtual Time GetCompressedBlockAckTimeout (void) const;
 
   void SetMaxMissedBeacons (uint32_t missed);
   void SetProbeRequestTimeout (Time timeout);
--- a/src/devices/wifi/wifi-mac.cc	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/wifi-mac.cc	Wed Feb 03 20:34:52 2010 +0100
@@ -69,6 +69,63 @@
   return ctsTimeout;
 }
 
+Time
+WifiMac::GetDefaultBasicBlockAckDelay (void)
+{
+  // This value must be rivisited
+  return MicroSeconds (250);
+}
+Time
+WifiMac::GetDefaultCompressedBlockAckDelay (void)
+{
+  // This value must be rivisited
+  return MicroSeconds (68);
+}
+Time
+WifiMac::GetDefaultBasicBlockAckTimeout (void)
+{
+  Time blockAckTimeout = GetDefaultSifs ();
+  blockAckTimeout += GetDefaultBasicBlockAckDelay ();
+  blockAckTimeout += MicroSeconds (GetDefaultMaxPropagationDelay ().GetMicroSeconds () * 2);
+  blockAckTimeout += GetDefaultSlot ();
+  return blockAckTimeout;
+}
+Time
+WifiMac::GetDefaultCompressedBlockAckTimeout (void)
+{
+  Time blockAckTimeout = GetDefaultSifs ();
+  blockAckTimeout += GetDefaultCompressedBlockAckDelay ();
+  blockAckTimeout += MicroSeconds (GetDefaultMaxPropagationDelay ().GetMicroSeconds () * 2);
+  blockAckTimeout += GetDefaultSlot ();
+  return blockAckTimeout;
+}
+
+void
+WifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout)
+{
+  //this method must be implemented by QoS WifiMacs
+}
+
+Time
+WifiMac::GetBasicBlockAckTimeout (void) const
+{
+  //this method must be implemented by QoS WifiMacs
+  return MicroSeconds (0);
+}
+
+void
+WifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout)
+{
+  //this methos must be implemented by QoS WifiMacs
+}
+
+Time
+WifiMac::GetCompressedBlockAckTimeout (void) const
+{
+  //this method must be implemented by QoS WifiMacs
+  return MicroSeconds (0);
+}
+
 TypeId 
 WifiMac::GetTypeId (void)
 {
@@ -84,6 +141,16 @@
                    MakeTimeAccessor (&WifiMac::GetAckTimeout,
                                      &WifiMac::SetAckTimeout),
                    MakeTimeChecker ())
+    .AddAttribute ("BasicBlockAckTimeout", "When this timeout expires, the BASIC_BLOCK_ACK_REQ/BASIC_BLOCK_ACK handshake has failed.",
+                   TimeValue (GetDefaultBasicBlockAckTimeout ()),
+                   MakeTimeAccessor (&WifiMac::GetBasicBlockAckTimeout,
+                                     &WifiMac::SetBasicBlockAckTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("CompressedBlockAckTimeout", "When this timeout expires, the COMPRESSED_BLOCK_ACK_REQ/COMPRESSED_BLOCK_ACK handshake has failed.",
+                   TimeValue (GetDefaultCompressedBlockAckTimeout ()),
+                   MakeTimeAccessor (&WifiMac::GetCompressedBlockAckTimeout,
+                                     &WifiMac::SetCompressedBlockAckTimeout),
+                   MakeTimeChecker ())
     .AddAttribute ("Sifs", "The value of the SIFS constant.",
                    TimeValue (GetDefaultSifs ()),
                    MakeTimeAccessor (&WifiMac::SetSifs,
--- a/src/devices/wifi/wifi-mac.h	Wed Feb 03 20:34:51 2010 +0100
+++ b/src/devices/wifi/wifi-mac.h	Wed Feb 03 20:34:52 2010 +0100
@@ -179,6 +179,13 @@
    * \param linkDown the callback to invoke when the link becomes down.
    */
   virtual void SetLinkDownCallback (Callback<void> linkDown) = 0;
+  /* Next functions are not pure vitual so non Qos WifiMacs are not
+   * forced to implement them.
+   */
+  virtual void SetBasicBlockAckTimeout (Time blockAckTimeout);
+  virtual Time GetBasicBlockAckTimeout (void) const;
+  virtual void SetCompressedBlockAckTimeout (Time blockAckTimeout);
+  virtual Time GetCompressedBlockAckTimeout (void) const;
 
   /**
    * Public method used to fire a MacTx trace.  Implemented for encapsulation 
@@ -224,6 +231,10 @@
   static Time GetDefaultEifsNoDifs (void);
   static Time GetDefaultCtsAckDelay (void);
   static Time GetDefaultCtsAckTimeout (void);
+  static Time GetDefaultBasicBlockAckDelay (void);
+  static Time GetDefaultBasicBlockAckTimeout (void);
+  static Time GetDefaultCompressedBlockAckDelay (void);
+  static Time GetDefaultCompressedBlockAckTimeout (void);
   /**
    * \param standard the phy standard to be used
    *