From 83cf4909ecda989183487230c06cedf1c85a0774 Mon Sep 17 00:00:00 2001 From: Mirko Banchi Date: Wed, 3 Feb 2010 20:34:52 +0100 Subject: [PATCH] add block ack timeouts --- src/devices/wifi/edca-txop-n.cc | 17 +++++++ src/devices/wifi/edca-txop-n.h | 1 + src/devices/wifi/mac-low.cc | 74 +++++++++++++++++++++++++---- src/devices/wifi/mac-low.h | 18 +++++++ src/devices/wifi/qadhoc-wifi-mac.cc | 24 ++++++++++ src/devices/wifi/qadhoc-wifi-mac.h | 4 ++ src/devices/wifi/qap-wifi-mac.cc | 24 ++++++++++ src/devices/wifi/qap-wifi-mac.h | 4 ++ src/devices/wifi/qsta-wifi-mac.cc | 24 ++++++++++ src/devices/wifi/qsta-wifi-mac.h | 4 ++ src/devices/wifi/wifi-mac.cc | 67 ++++++++++++++++++++++++++ src/devices/wifi/wifi-mac.h | 11 +++++ 12 files changed, 264 insertions(+), 8 deletions(-) diff --git a/src/devices/wifi/edca-txop-n.cc b/src/devices/wifi/edca-txop-n.cc index e178d5290..5c1679ac7 100644 --- a/src/devices/wifi/edca-txop-n.cc +++ b/src/devices/wifi/edca-txop-n.cc @@ -87,6 +87,9 @@ public: 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 @@ EdcaTxopN::MissedAck (void) 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 EdcaTxopN::GetMsduAggregator (void) const { diff --git a/src/devices/wifi/edca-txop-n.h b/src/devices/wifi/edca-txop-n.h index fd06d7358..ef749b413 100644 --- a/src/devices/wifi/edca-txop-n.h +++ b/src/devices/wifi/edca-txop-n.h @@ -114,6 +114,7 @@ public: 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); diff --git a/src/devices/wifi/mac-low.cc b/src/devices/wifi/mac-low.cc index 593af174c..b11def366 100644 --- a/src/devices/wifi/mac-low.cc +++ b/src/devices/wifi/mac-low.cc @@ -117,6 +117,9 @@ void MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source) {} +void +MacLowTransmissionListener::MissedBlockAck (void) +{} MacLowDcfListener::MacLowDcfListener () {} MacLowDcfListener::~MacLowDcfListener () @@ -319,6 +322,7 @@ MacLow::MacLow () m_fastAckTimeoutEvent (), m_superFastAckTimeoutEvent (), m_fastAckFailedTimeoutEvent (), + m_blockAckTimeoutEvent (), m_ctsTimeoutEvent (), m_sendCtsEvent (), m_sendAckEvent (), @@ -353,6 +357,7 @@ MacLow::DoDispose (void) 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 @@ MacLow::CancelAllEvents (void) 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 @@ MacLow::SetAckTimeout (Time ackTimeout) { 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 @@ MacLow::GetAckTimeout (void) const { 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 @@ MacLow::ReceiveOk (Ptr packet, double rxSnr, WifiMode txMode, WifiPreamb } } 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 "<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 @@ MacLow::GetAckDuration (Mac48Address to, WifiMode dataTxMode) const 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 @@ MacLow::FastAckTimeout (void) } } 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 @@ MacLow::StartDataTxTimers (void) 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 @@ MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Addre { 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); diff --git a/src/devices/wifi/mac-low.h b/src/devices/wifi/mac-low.h index d21ccb611..85c57eaa9 100644 --- a/src/devices/wifi/mac-low.h +++ b/src/devices/wifi/mac-low.h @@ -94,6 +94,16 @@ public: * of a block ack must redefine this function. */ 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. @@ -338,6 +348,8 @@ public: 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 @@ public: 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 @@ private: 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 @@ private: 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 @@ private: Mac48Address m_self; Mac48Address m_bssid; Time m_ackTimeout; + Time m_basicBlockAckTimeout; + Time m_compressedBlockAckTimeout; Time m_ctsTimeout; Time m_sifs; Time m_slotTime; diff --git a/src/devices/wifi/qadhoc-wifi-mac.cc b/src/devices/wifi/qadhoc-wifi-mac.cc index 89831ecbc..45b27a66e 100644 --- a/src/devices/wifi/qadhoc-wifi-mac.cc +++ b/src/devices/wifi/qadhoc-wifi-mac.cc @@ -147,6 +147,18 @@ QadhocWifiMac::SetAckTimeout (Time ackTimeout) 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 @@ QadhocWifiMac::GetAckTimeout (void) const 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 { diff --git a/src/devices/wifi/qadhoc-wifi-mac.h b/src/devices/wifi/qadhoc-wifi-mac.h index c579de269..0ebad8a5b 100644 --- a/src/devices/wifi/qadhoc-wifi-mac.h +++ b/src/devices/wifi/qadhoc-wifi-mac.h @@ -74,6 +74,10 @@ public: 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: diff --git a/src/devices/wifi/qap-wifi-mac.cc b/src/devices/wifi/qap-wifi-mac.cc index d477cd62a..7bdd3199a 100644 --- a/src/devices/wifi/qap-wifi-mac.cc +++ b/src/devices/wifi/qap-wifi-mac.cc @@ -197,6 +197,18 @@ QapWifiMac::SetAckTimeout (Time ackTimeout) m_low->SetAckTimeout (ackTimeout); } +void +QapWifiMac::SetBasicBlockAckTimeout (Time blockAckTimeout) +{ + m_low->SetBasicBlockAckTimeout (blockAckTimeout); +} + +void +QapWifiMac::SetCompressedBlockAckTimeout (Time blockAckTimeout) +{ + m_low->SetCompressedBlockAckTimeout (blockAckTimeout); +} + void QapWifiMac::SetCtsTimeout (Time ctsTimeout) { @@ -233,6 +245,18 @@ QapWifiMac::GetAckTimeout (void) const return m_low->GetAckTimeout (); } +Time +QapWifiMac::GetBasicBlockAckTimeout () const +{ + return m_low->GetBasicBlockAckTimeout (); +} + +Time +QapWifiMac::GetCompressedBlockAckTimeout () const +{ + return m_low->GetCompressedBlockAckTimeout (); +} + Time QapWifiMac::GetCtsTimeout (void) const { diff --git a/src/devices/wifi/qap-wifi-mac.h b/src/devices/wifi/qap-wifi-mac.h index 41709944e..55824d0ad 100644 --- a/src/devices/wifi/qap-wifi-mac.h +++ b/src/devices/wifi/qap-wifi-mac.h @@ -82,6 +82,10 @@ public: 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; diff --git a/src/devices/wifi/qsta-wifi-mac.cc b/src/devices/wifi/qsta-wifi-mac.cc index e1f32d259..f2c018209 100644 --- a/src/devices/wifi/qsta-wifi-mac.cc +++ b/src/devices/wifi/qsta-wifi-mac.cc @@ -169,6 +169,18 @@ QstaWifiMac::SetAckTimeout (Time ackTimeout) 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 @@ QstaWifiMac::GetAckTimeout (void) const 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 { diff --git a/src/devices/wifi/qsta-wifi-mac.h b/src/devices/wifi/qsta-wifi-mac.h index 8aea94cad..4e30b4deb 100644 --- a/src/devices/wifi/qsta-wifi-mac.h +++ b/src/devices/wifi/qsta-wifi-mac.h @@ -81,6 +81,10 @@ public: 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); diff --git a/src/devices/wifi/wifi-mac.cc b/src/devices/wifi/wifi-mac.cc index 629fb5a6d..5b88f9eaa 100644 --- a/src/devices/wifi/wifi-mac.cc +++ b/src/devices/wifi/wifi-mac.cc @@ -69,6 +69,63 @@ WifiMac::GetDefaultCtsAckTimeout (void) 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 @@ WifiMac::GetTypeId (void) 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, diff --git a/src/devices/wifi/wifi-mac.h b/src/devices/wifi/wifi-mac.h index eb5f0841a..73d42dc86 100644 --- a/src/devices/wifi/wifi-mac.h +++ b/src/devices/wifi/wifi-mac.h @@ -179,6 +179,13 @@ public: * \param linkDown the callback to invoke when the link becomes down. */ virtual void SetLinkDownCallback (Callback 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 @@ private: 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 *