src/devices/wifi/mac-low.cc
changeset 5958 dd0accd82659
parent 5957 dd5ece55acb9
child 5964 8a59a619c30e
--- 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);