src/wifi/model/edca-txop-n.h
author Sébastien Deronne <sebastien.deronne@gmail.com>
Sun, 21 Jun 2015 00:23:45 +0200
changeset 11450 9f4ae69f12b7
parent 11352 a1f6f647d516
permissions -rw-r--r--
cleanup wifi module

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2006, 2009 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
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
 *          Mirko Banchi <mk.banchi@gmail.com>
 */
#ifndef EDCA_TXOP_N_H
#define EDCA_TXOP_N_H

#include "ns3/object.h"
#include "ns3/mac48-address.h"
#include "ns3/packet.h"
#include "wifi-mode.h"
#include "wifi-mac-header.h"
#include "wifi-remote-station-manager.h"
#include "qos-utils.h"
#include "dcf.h"
#include "ctrl-headers.h"
#include "block-ack-manager.h"
#include <map>
#include <list>

namespace ns3 {

class DcfState;
class DcfManager;
class MacLow;
class MacTxMiddle;
class WifiMac;
class WifiMacParameters;
class WifiMacQueue;
class RandomStream;
class QosBlockedDestinations;
class MsduAggregator;
class MgtAddBaResponseHeader;
class BlockAckManager;
class MgtDelBaHeader;

/**
 * Enumeration for type of station
 */
enum TypeOfStation
{
  STA,
  AP,
  ADHOC_STA,
  MESH,
  HT_STA,
  HT_AP,
  HT_ADHOC_STA,
  OCB
};


/**
 * \ingroup wifi
 * This queue contains packets for a particular access class.
 * possibles access classes are:
 *
 *   -AC_VO : voice, tid = 6,7         ^
 *   -AC_VI : video, tid = 4,5         |
 *   -AC_BE : best-effort, tid = 0,3   |  priority
 *   -AC_BK : background, tid = 1,2    |
 *
 * For more details see section 9.1.3.1 in 802.11 standard.
 */
class EdcaTxopN : public Dcf
{
public:
  /**
   * typedef for a callback to invoke when a
   * packet transmission was completed successfully.
   */
  typedef Callback <void, const WifiMacHeader&> TxOk;
  /**
   * typedef for a callback to invoke when a
   * packet transmission was failed.
   */
  typedef Callback <void, const WifiMacHeader&> TxFailed;

  static TypeId GetTypeId (void);
  EdcaTxopN ();
  virtual ~EdcaTxopN ();
  void DoDispose ();

  /**
   * Set MacLow associated with this EdcaTxopN.
   *
   * \param low MacLow
   */
  void SetLow (Ptr<MacLow> low);
  void SetTxMiddle (MacTxMiddle *txMiddle);
  /**
   * Set DcfManager this EdcaTxopN is associated to.
   *
   * \param manager DcfManager
   */
  void SetManager (DcfManager *manager);
  /**
   * \param callback the callback to invoke when a
   * packet transmission was completed successfully.
   */
  void SetTxOkCallback (TxOk callback);
  /**
   * \param callback the callback to invoke when a
   * packet transmission was completed unsuccessfully.
   */
  void SetTxFailedCallback (TxFailed callback);
  /**
   * Set WifiRemoteStationsManager this EdcaTxopN is associated to.
   *
   * \param remoteManager WifiRemoteStationManager
   */
  void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager);
  /**
   * Set type of station with the given type.
   *
   * \param type
   */
  void SetTypeOfStation (enum TypeOfStation type);
  /**
   * Return type of station.
   *
   * \return type of station
   */
  enum TypeOfStation GetTypeOfStation (void) const;
  /**
   * Return the packet queue associated with this EdcaTxopN.
   *
   * \return WifiMacQueue
   */
  Ptr<WifiMacQueue > GetEdcaQueue () const;

  virtual void SetMinCw (uint32_t minCw);
  virtual void SetMaxCw (uint32_t maxCw);
  virtual void SetAifsn (uint32_t aifsn);
  virtual uint32_t GetMinCw (void) const;
  virtual uint32_t GetMaxCw (void) const;
  virtual uint32_t GetAifsn (void) const;

  /**
   * Return the MacLow associated with this EdcaTxopN.
   *
   * \return MacLow
   */
  Ptr<MacLow> Low (void);

  Ptr<MsduAggregator> GetMsduAggregator (void) const;
  /**
   * \param recipient address of the peer station
   * \param tid traffic ID.
   * \return true if a block ack agreement exists, false otherwise
   *
   * Checks if a block ack agreement exists with station addressed by
   * <i>recipient</i> for tid <i>tid</i>.
   */
  bool GetBaAgreementExists (Mac48Address address, uint8_t tid);
  /**
   * \param recipient address of peer station involved in block ack mechanism.
   * \param tid traffic ID.
   * \return the number of packets buffered for a specified agreement
   *
   * Returns number of packets buffered for a specified agreement.
   */
  uint32_t GetNOutstandingPacketsInBa (Mac48Address address, uint8_t tid);
  /**
   * \param recipient address of peer station involved in block ack mechanism.
   * \param tid traffic ID.
   * \return the number of packets for a specific agreement that need retransmission
   *
   * Returns number of packets for a specific agreement that need retransmission.
   */
  uint32_t GetNRetryNeededPackets (Mac48Address recipient, uint8_t tid) const;
  /**
   * \param recipient address of peer station involved in block ack mechanism.
   * \param tid Ttraffic ID of transmitted packet.
   *
   * This function resets the status of OriginatorBlockAckAgreement after the transfer
   * of an A-MPDU with ImmediateBlockAck policy (i.e. no BAR is scheduled)
   */
  void CompleteAmpduTransfer (Mac48Address recipient, uint8_t tid);

  /* dcf notifications forwarded here */
  /**
   * Check if the EDCAF requires access.
   *
   * \return true if the EDCAF requires access,
   *         false otherwise
   */
  bool NeedsAccess (void) const;
  /**
   * Notify the EDCAF that access has been granted.
   */
  void NotifyAccessGranted (void);
  /**
   * Notify the EDCAF that internal collision has occurred.
   */
  void NotifyInternalCollision (void);
  /**
   * Notify the EDCAF that collision has occurred.
   */
  void NotifyCollision (void);
  /**
   * When a channel switching occurs, enqueued packets are removed.
   */
  void NotifyChannelSwitching (void);
  /**
   * When sleep operation occurs, re-insert pending packet into front of the queue
   */
  void NotifySleep (void);
  /**
   * When wake up operation occurs, restart channel access
   */
  void NotifyWakeUp (void);

  /* Event handlers */
  /**
   * Event handler when a CTS is received.
   *
   * \param snr
   * \param txMode
   */
  void GotCts (double snr, WifiMode txMode);
  /**
   * Event handler when a CTS timeout has occurred.
   */
  void MissedCts (void);
  /**
   * Event handler when an ACK is received.
   *
   * \param snr
   * \param txMode
   */
  void GotAck (double snr, WifiMode txMode);
  /**
   * Event handler when a Block ACK is received.
   *
   * \param blockAck
   * \param recipient
   * \param txMode
   */
  void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, WifiMode txMode);
  /**
   * Event handler when a Block ACK timeout has occurred.
   */
  void MissedBlockAck (void);
  void GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address recipient);
  void GotDelBaFrame (const MgtDelBaHeader *delBaHdr, Mac48Address recipient);
  /**
   * Event handler when an ACK is received.
   */
  void MissedAck (void);
  /**
   * Start transmission for the next fragment.
   * This is called for fragment only.
   */
  void StartNext (void);
  /**
   * Cancel the transmission.
   */
  void Cancel (void);
  /**
   * Event handler when a transmission that
   * does not require an ACK has completed.
   */
  void EndTxNoAck (void);
  /**
   * Restart access request if needed.
   */
  void RestartAccessIfNeeded (void);
  /**
   * Request access from DCF manager if needed.
   */
  void StartAccessIfNeeded (void);
  /**
   * Check if the current packet should be sent with a RTS protection.
   *
   * \return true if RTS protection should be used,
   *         false otherwise
   */
  bool NeedRts (void);
  /**
   * Check if RTS should be re-transmitted if CTS was missed.
   *
   * \return true if RTS should be re-transmitted,
   *         false otherwise
   */
  bool NeedRtsRetransmission (void);
  /**
   * Check if DATA should be re-transmitted if ACK was missed.
   *
   * \return true if DATA should be re-transmitted,
   *         false otherwise
   */
  bool NeedDataRetransmission (void);
  /**
   * Check if Block ACK Request should be re-transmitted.
   *
   * \return true if BAR should be re-transmitted,
   *         false otherwise
   */
  bool NeedBarRetransmission (void);
  /**
   * Check if the current packet should be fragmented.
   *
   * \return true if the current packet should be fragmented,
   *         false otherwise
   */
  bool NeedFragmentation (void) const;
  /**
   * Calculate the size of the next fragment.
   *
   * \return the size of the next fragment
   */
  uint32_t GetNextFragmentSize (void);
  /**
   * Calculate the size of the current fragment.
   *
   * \return the size of the current fragment
   */
  uint32_t GetFragmentSize (void);
  /**
   * Calculate the offset for the current fragment.
   *
   * \return the offset for the current fragment
   */
  uint32_t GetFragmentOffset (void);
  /**
   * Check if the current fragment is the last fragment.
   *
   * \return true if the current fragment is the last fragment,
   *         false otherwise
   */
  bool IsLastFragment (void) const;
  /**
   * Continue to the next fragment. This method simply
   * increments the internal variable that keep track
   * of the current fragment number.
   */
  void NextFragment (void);
  /**
   * Get the next fragment from the packet with
   * appropriate Wifi header for the fragment.
   *
   * \param hdr
   * \return the fragment with the current fragment number
   */
  Ptr<Packet> GetFragmentPacket (WifiMacHeader *hdr);

  /**
   * Set the access category of this EDCAF.
   *
   * \param ac
   */
  void SetAccessCategory (enum AcIndex ac);

  /**
   * \param packet packet to send
   * \param hdr header of packet to send.
   *
   * Store the packet in the internal queue until it
   * can be sent safely.
   */
  void Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr);

  void SetMsduAggregator (Ptr<MsduAggregator> aggr);

  /**
   * \param packet packet to send
   * \param hdr header of packet to send.
   *
   * Store the packet in the front of the internal queue until it
   * can be sent safely.
   */
  void PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr);

  /**
   * Complete block ACK configuration.
   */
  void CompleteConfig (void);

  /**
   * Set threshold for block ACK mechanism. If number of packets in the
   * queue reaches the threshold, block ACK mechanism is used.
   *
   * \param threshold
   */
  void SetBlockAckThreshold (uint8_t threshold);
  /**
   * Return the current threshold for block ACK mechanism.
   *
   * \return the current threshold for block ACK mechanism
   */
  uint8_t GetBlockAckThreshold (void) const;

  void SetBlockAckInactivityTimeout (uint16_t timeout);
  void SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator);
  void CompleteMpduTx (Ptr<const Packet> packet, WifiMacHeader hdr, Time tstamp);
  bool GetAmpduExist (void);
  void SetAmpduExist (bool ampdu);

  /**
   * Return the next sequence number for the given header.
   *
   * \param hdr Wi-Fi header
   *
   * \return the next sequence number
   */
  uint16_t GetNextSequenceNumberfor (WifiMacHeader *hdr);
  /**
   * Return the next sequence number for the Traffic ID and destination, but do not pick it (i.e. the current sequence number remains unchanged).
   *
   * \param hdr Wi-Fi header
   *
   * \return the next sequence number
   */
  uint16_t PeekNextSequenceNumberfor (WifiMacHeader *hdr);
  /**
   * Remove a packet after you peek in the retransmit queue and get it
   */
  void RemoveRetransmitPacket (uint8_t tid, Mac48Address recipient, uint16_t seqnumber);
  /*
   * Peek in retransmit queue and get the next packet without removing it from the queue
   */
  Ptr<const Packet> PeekNextRetransmitPacket (WifiMacHeader &header, Mac48Address recipient, uint8_t tid, Time *timestamp);
  /**
   * The packet we sent was successfully received by the receiver
   *
   * \param hdr the header of the packet that we successfully sent
   */
  void BaTxOk (const WifiMacHeader &hdr);
  /**
   * The packet we sent was successfully received by the receiver
   *
   * \param hdr the header of the packet that we failed to sent
   */
  void BaTxFailed (const WifiMacHeader &hdr);

  /**
   * Assign a fixed random variable stream number to the random variables
   * used by this model.  Return the number of streams (possibly zero) that
   * have been assigned.
   *
   * \param stream first stream index to use
   * \return the number of stream indices assigned by this model
   */
  int64_t AssignStreams (int64_t stream);


private:
  void DoInitialize ();
  /**
   * This functions are used only to correctly set addresses in a-msdu subframe.
   * If aggregating sta is a STA (in an infrastructured network):
   *   SA = Address2
   *   DA = Address3
   * If aggregating sta is an AP
   *   SA = Address3
   *   DA = Address1
   *
   * \param hdr
   * \return Mac48Address
   */
  Mac48Address MapSrcAddressForAggregation (const WifiMacHeader &hdr);
  Mac48Address MapDestAddressForAggregation (const WifiMacHeader &hdr);
  EdcaTxopN &operator = (const EdcaTxopN &);
  EdcaTxopN (const EdcaTxopN &);

  /**
   * If number of packets in the queue reaches m_blockAckThreshold value, an ADDBA Request frame
   * is sent to destination in order to setup a block ack.
   *
   * \return true if we tried to set up block ACK, false otherwise
   */
  bool SetupBlockAckIfNeeded ();
  /**
   * Sends an ADDBA Request to establish a block ack agreement with sta
   * addressed by <i>recipient</i> for tid <i>tid</i>.
   *
   * \param recipient
   * \param tid
   * \param startSeq
   * \param timeout
   * \param immediateBAck
   */
  void SendAddBaRequest (Mac48Address recipient, uint8_t tid, uint16_t startSeq,
                         uint16_t timeout, bool immediateBAck);
  /**
   * After that all packets, for which a block ack agreement was established, have been
   * transmitted, we have to send a block ack request.
   *
   * \param bar
   */
  void SendBlockAckRequest (const struct Bar &bar);
  /**
   * For now is typically invoked to complete transmission of a packets sent with ack policy
   * Block Ack: the packet is buffered and dcf is reset.
   */
  void CompleteTx (void);
  /**
   * Verifies if dequeued packet has to be transmitted with ack policy Block Ack. This happens
   * if an established block ack agreement exists with the receiver.
   */
  void VerifyBlockAck (void);

  AcIndex m_ac;
  class Dcf;
  class TransmissionListener;
  class AggregationCapableTransmissionListener;
  friend class Dcf;
  friend class TransmissionListener;
  Dcf *m_dcf;
  DcfManager *m_manager;
  Ptr<WifiMacQueue> m_queue;
  TxOk m_txOkCallback;
  TxFailed m_txFailedCallback;
  Ptr<MacLow> m_low;
  MacTxMiddle *m_txMiddle;
  TransmissionListener *m_transmissionListener;
  AggregationCapableTransmissionListener *m_blockAckListener;
  RandomStream *m_rng;
  Ptr<WifiRemoteStationManager> m_stationManager;
  uint8_t m_fragmentNumber;

  /* current packet could be a simple MSDU or, if an aggregator for this queue is
     present, could be an A-MSDU.
   */
  Ptr<const Packet> m_currentPacket;

  WifiMacHeader m_currentHdr;
  Ptr<MsduAggregator> m_aggregator;
  TypeOfStation m_typeOfStation;
  QosBlockedDestinations *m_qosBlockedDestinations;
  BlockAckManager *m_baManager;
  /*
   * Represents the minimum number of packets for use of block ack.
   */
  uint8_t m_blockAckThreshold;
  enum BlockAckType m_blockAckType;
  Time m_currentPacketTimestamp;
  uint16_t m_blockAckInactivityTimeout;
  struct Bar m_currentBar;
  bool m_ampduExist;
};

} //namespace ns3

#endif /* EDCA_TXOP_N_H */