src/devices/wifi/mac-low.h
changeset 6068 a2127017ecb4
parent 6065 0f012e7d9128
parent 5964 8a59a619c30e
child 6273 8d70de29d514
--- 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 <mathieu.lacage@sophia.inria.fr>
+ * Author: Mirko Banchi <mk.banchi@gmail.com>
  */
 #ifndef MAC_LOW_H
 #define MAC_LOW_H
@@ -23,21 +25,27 @@
 #include <vector>
 #include <stdint.h>
 #include <ostream>
+#include <map>
 
 #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 <i>originator</i>, <i>tid</i>.
+   * 
+   * 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 <i>originator</i>
+   * for tid <i>tid</i>. If the agreement exists, tears down it. This function is typically
+   * invoked when a DELBA frame is received from <i>originator</i>.
+   */
+  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<const Packet> packet, const WifiMacHeader *hdr) const;
@@ -380,8 +497,10 @@
   WifiMode GetDataTxMode (Ptr<const Packet> 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 <i>seq</i>. 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> 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 <i>blockAck</i> 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 <i>block ack</i>
+   * 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<WifiPhy> 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<Ptr<Packet>, WifiMacHeader> BufferedPacket;
+  typedef std::list<BufferedPacket>::iterator BufferedPacketI;
+
+  typedef std::pair<Mac48Address, uint8_t> AgreementKey;
+  typedef std::pair<BlockAckAgreement, std::list<BufferedPacket> > AgreementValue;
+
+  typedef std::map<AgreementKey, AgreementValue> Agreements;
+  typedef std::map<AgreementKey, AgreementValue>::iterator AgreementsI;
+
+  Agreements m_bAckAgreements;
+  
+  typedef std::map<AccessClass, MacLowBlockAckEventListener*> QueueListeners;
+  QueueListeners m_edcaListeners;
 };
 
 } // namespace ns3