diff -r ccbdc2b19ea5 -r a2127017ecb4 src/devices/wifi/mac-low.h --- a/src/devices/wifi/mac-low.h Thu Feb 25 13:51:59 2010 +0100 +++ b/src/devices/wifi/mac-low.h Thu Feb 25 14:17:21 2010 +0100 @@ -1,6 +1,7 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2005, 2006 INRIA + * Copyright (c) 2009 MIRKO BANCHI * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Author: Mirko Banchi */ #ifndef MAC_LOW_H #define MAC_LOW_H @@ -23,21 +25,27 @@ #include #include #include +#include #include "wifi-mac-header.h" #include "wifi-mode.h" #include "wifi-preamble.h" #include "wifi-remote-station-manager.h" +#include "ctrl-headers.h" +#include "mgt-headers.h" +#include "block-ack-agreement.h" #include "ns3/mac48-address.h" #include "ns3/callback.h" #include "ns3/event-id.h" #include "ns3/packet.h" #include "ns3/nstime.h" +#include "qos-utils.h" namespace ns3 { class WifiPhy; class WifiMac; +class EdcaTxopN; /** * \brief listen to events coming from ns3::MacLow. @@ -76,6 +84,29 @@ */ virtual void MissedAck (void) = 0; /** + * \param blockAck Block ack response header + * \param source Address of block ack sender + * + * Invoked when ns3::MacLow receives a block ack frame. + * Block ack frame is received after a block ack request + * and contains information about the correct reception + * of a set of packet for which a normal ack wasn't send. + * Default implementation for this method is empty. Every + * queue that intends to be notified by MacLow of reception + * 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. * The listener is expected to call again MacLow::StartTransmission @@ -119,6 +150,25 @@ }; /** + * \brief listen for block ack events. + */ +class MacLowBlockAckEventListener { +public: + MacLowBlockAckEventListener (); + virtual ~MacLowBlockAckEventListener (); + /** + * Typically is called in order to notify EdcaTxopN that a block ack inactivity + * timeout occurs for the block ack agreement identified by the pair originator, tid. + * + * Rx station maintains an inactivity timer for each block ack + * agreement. Timer is reset when a frame with ack policy block ack + * or a block ack request are received. When this timer reaches zero + * this method is called and a delba frame is scheduled for transmission. + */ + virtual void BlockAckInactivityTimeout (Mac48Address originator, uint8_t tid) = 0; +}; + +/** * \brief control how a packet is transmitted. * * The ns3::MacLow::StartTransmission method expects @@ -157,6 +207,18 @@ */ void EnableSuperFastAck (void); /** + * Wait BASICBLOCKACKTimeout for a Basic Block Ack Response frame. + */ + void EnableBasicBlockAck (void); + /** + * Wait COMPRESSEDBLOCKACKTimeout for a Compressed Block Ack Response frame. + */ + void EnableCompressedBlockAck (void); + /** + * NOT IMPLEMENTED FOR NOW + */ + void EnableMultiTidBlockAck (void); + /** * Send a RTS, and wait CTSTimeout for a CTS. If we get a * CTS on time, call MacLowTransmissionListener::GotCts * and send data. Otherwise, call MacLowTransmissionListener::MissedCts @@ -233,6 +295,24 @@ */ bool MustWaitSuperFastAck (void) const; /** + * \returns true if block ack mechanism is used, false otherwise. + * + * \sa EnableBlockAck + */ + bool MustWaitBasicBlockAck (void) const; + /** + * \returns true if compressed block ack mechanism is used, false otherwise. + * + * \sa EnableCompressedBlockAck + */ + bool MustWaitCompressedBlockAck (void) const; + /** + * \returns true if multi-tid block ack mechanism is used, false otherwise. + * + * \sa EnableMultiTidBlockAck + */ + bool MustWaitMultiTidBlockAck (void) const; + /** * \returns true if RTS should be sent and CTS waited for before * sending data, false otherwise. */ @@ -262,7 +342,10 @@ ACK_NONE, ACK_NORMAL, ACK_FAST, - ACK_SUPER_FAST + ACK_SUPER_FAST, + BLOCK_ACK_BASIC, + BLOCK_ACK_COMPRESSED, + BLOCK_ACK_MULTI_TID } m_waitAck; bool m_sendRts; Time m_overrideDurationId; @@ -286,6 +369,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); @@ -293,6 +378,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; @@ -364,9 +451,39 @@ * occurs, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled. */ void NotifySwitchingStartNow (Time duration); + /** + * \param respHdr Add block ack response from originator (action frame). + * \param originator Address of peer station involved in block ack mechanism. + * \param startingSeq Sequence number of the first MPDU of all packets for which block ack was negotiated. + * + * This function is typically invoked only by ns3::QapWifiMac and ns3::QstaWifiMac. + * If we are transmitting an Add block ack response, MacLow must allocate buffers to collect + * all correctly received packets belonging to category for which block ack was negotiated. + * It's needed in order to send a Block ack after corresponding originator's Block ack request. + */ + void CreateBlockAckAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Address originator, + uint16_t startingSeq); + /** + * \param originator Address of peer partecipating in Block Ack mechanism. + * \param tid TID for which Block Ack was created. + * + * Checks if exists an established block ack agreement with originator + * for tid tid. If the agreement exists, tears down it. This function is typically + * invoked when a DELBA frame is received from originator. + */ + void DestroyBlockAckAgreement (Mac48Address originator, uint8_t tid); + /** + * \param ac Access class managed by the queue. + * \param listener The listener for the queue. + * + * The lifetime of the registered listener is typically equal to the lifetime of the queue + * associated to this AC. + */ + void RegisterBlockAckListenerForAc (enum AccessClass ac, MacLowBlockAckEventListener *listener); private: void CancelAllEvents (void); uint32_t GetAckSize (void) const; + uint32_t GetBlockAckSize (enum BlockAckType type) const; uint32_t GetRtsSize (void) const; uint32_t GetCtsSize (void) const; uint32_t GetSize (Ptr packet, const WifiMacHeader *hdr) const; @@ -380,8 +497,10 @@ WifiMode GetDataTxMode (Ptr packet, const WifiMacHeader *hdr) const; WifiMode GetCtsTxModeForRts (Mac48Address to, WifiMode rtsTxMode) const; WifiMode GetAckTxModeForData (Mac48Address to, WifiMode dataTxMode) const; + Time GetCtsDuration (Mac48Address to, WifiMode rtsTxMode) const; Time GetAckDuration (Mac48Address to, WifiMode dataTxMode) const; + Time GetBlockAckDuration (Mac48Address to, WifiMode blockAckReqTxMode, enum BlockAckType type) const; void NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble); void DoNavResetNow (Time duration); bool DoNavStartNow (Time duration); @@ -397,6 +516,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); @@ -408,6 +528,53 @@ void SendCurrentTxPacket (void); void StartDataTxTimers (void); virtual void DoDispose (void); + /** + * \param originator Address of peer partecipating in Block Ack mechanism. + * \param tid TID for which Block Ack was created. + * \param seq Starting sequence + * + * This function forward up all completed "old" packets with sequence number + * smaller than seq. All comparison are performed circularly mod 4096. + */ + void RxCompleteBufferedPacketsWithSmallerSequence (uint16_t seq, Mac48Address originator, uint8_t tid); + /** + * \param originator Address of peer partecipating in Block Ack mechanism. + * \param tid TID for which Block Ack was created. + * + * This method is typically invoked when a MPDU with ack policy + * subfield set to Normal Ack is received and a block ack agreement + * for that packet exists. + * This happens when the originator of block ack has only few MPDUs to send. + * All completed MSDUs starting with starting sequence number of block ack + * agreement are forward up to WifiMac until there is an incomplete MSDU. + * See section 9.10.4 in IEEE802.11 standard for more details. + */ + void RxCompleteBufferedPackets (Mac48Address originator, uint8_t tid); + /* + * This method checks if exists a valid established block ack agreement. + * If there is, store the packet without pass it up to WifiMac. The packet is buffered + * in order of increasing sequence control field. All comparison are performed + * circularly modulo 2^12. + */ + bool StoreMpduIfNeeded (Ptr packet, WifiMacHeader hdr); + /* + * Invoked after that a block ack request has been received. Looks for corresponding + * block ack agreement and creates block ack bitmap on a received packets basis. + */ + void SendBlockAckAfterBlockAckRequest (const CtrlBAckRequestHeader reqHdr, Mac48Address originator, + Time duration, WifiMode blockAckReqTxMode); + /* + * This method creates block ack frame with header equals to blockAck and start its transmission. + */ + void SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate, + Time duration, WifiMode blockAckReqTxMode); + /* + * Every time that a block ack request or a packet with ack policy equals to block ack + * are received, if a relative block ack agreement exists and the value of inactivity timeout + * is not 0, the timer is reset. + * see section 11.5.3 in IEEE802.11e for more details. + */ + void ResetBlockAckInactivityTimerIfNeeded (BlockAckAgreement &agreement); void SetupPhyMacLowListener (Ptr phy); @@ -422,6 +589,7 @@ EventId m_fastAckTimeoutEvent; EventId m_superFastAckTimeoutEvent; EventId m_fastAckFailedTimeoutEvent; + EventId m_blockAckTimeoutEvent; EventId m_ctsTimeoutEvent; EventId m_sendCtsEvent; EventId m_sendAckEvent; @@ -436,6 +604,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; @@ -446,6 +616,23 @@ // Listerner needed to monitor when a channel switching occurs. class PhyMacLowListener *m_phyMacLowListener; + + /* + * BlockAck data structures. + */ + typedef std::pair, WifiMacHeader> BufferedPacket; + typedef std::list::iterator BufferedPacketI; + + typedef std::pair AgreementKey; + typedef std::pair > AgreementValue; + + typedef std::map Agreements; + typedef std::map::iterator AgreementsI; + + Agreements m_bAckAgreements; + + typedef std::map QueueListeners; + QueueListeners m_edcaListeners; }; } // namespace ns3