1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #ifndef HE_FRAME_EXCHANGE_MANAGER_H
22 #define HE_FRAME_EXCHANGE_MANAGER_H
23 
24 #include "ns3/vht-frame-exchange-manager.h"
25 #include "mu-snr-tag.h"
26 #include <map>
27 #include <unordered_map>
28 
29 namespace ns3 {
30 
31 class MultiUserScheduler;
32 class ApWifiMac;
33 class StaWifiMac;
34 class CtrlTriggerHeader;
35 
36 /**
37  * Map of PSDUs indexed by STA-ID
38  */
39 typedef std::unordered_map <uint16_t /* staId */, Ptr<WifiPsdu> /* PSDU */> WifiPsduMap;
40 /**
41  * Map of const PSDUs indexed by STA-ID
42  */
43 typedef std::unordered_map <uint16_t /* staId */, Ptr<const WifiPsdu> /* PSDU */> WifiConstPsduMap;
44 
45 /**
46  * \ingroup wifi
47  *
48  * HeFrameExchangeManager handles the frame exchange sequences
49  * for HE stations.
50  */
51 class HeFrameExchangeManager : public VhtFrameExchangeManager
52 {
53 public:
54   /**
55    * \brief Get the type ID.
56    * \return the object TypeId
57    */
58   static TypeId GetTypeId (void);
59   HeFrameExchangeManager ();
60   virtual ~HeFrameExchangeManager ();
61 
62   uint16_t GetSupportedBaBufferSize (void) const override;
63   bool StartFrameExchange (Ptr<QosTxop> edca, Time availableTime, bool initialFrame) override;
64   void SetWifiMac (const Ptr<RegularWifiMac> mac) override;
65   void CalculateAcknowledgmentTime (WifiAcknowledgment* acknowledgment) const override;
66 
67   /**
68    * Set the Multi-user Scheduler associated with this Frame Exchange Manager.
69    *
70    * \param muScheduler the Multi-user Scheduler associated with this Frame Exchange Manager
71    */
72   void SetMultiUserScheduler (const Ptr<MultiUserScheduler> muScheduler);
73 
74   /**
75    * Get the PSDU in the given PSDU map that is addressed to the given MAC address,
76    * if any, or a null pointer, otherwise.
77    *
78    * \param to the MAC address
79    * \param psduMap the PSDU map
80    * \return the PSDU, if any, or a null pointer, otherwise
81    */
82   static Ptr<WifiPsdu> GetPsduTo (Mac48Address to, const WifiPsduMap& psduMap);
83 
84   /**
85    * Set the UL Target RSSI subfield of every User Info fields of the given
86    * Trigger Frame to the most recent RSSI observed from the corresponding
87    * station.
88    *
89    * \param trigger the given Trigger Frame
90    */
91   virtual void SetTargetRssi (CtrlTriggerHeader& trigger) const;
92 
93 protected:
94   void DoDispose () override;
95 
96   void ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rxSignalInfo,
97                     const WifiTxVector& txVector, bool inAmpdu) override;
98   void EndReceiveAmpdu (Ptr<const WifiPsdu> psdu, const RxSignalInfo& rxSignalInfo,
99                         const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus) override;
100   Time GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
101                       const WifiTxParameters& txParams) const override;
102   bool SendMpduFromBaManager (Ptr<QosTxop> edca, Time availableTime, bool initialFrame) override;
103 
104   /**
105    * Send a map of PSDUs as a DL MU PPDU.
106    * Note that both <i>psduMap</i> and <i>txParams</i> are moved to m_psduMap and
107    * m_txParams, respectively, and hence are left in an undefined state.
108    *
109    * \param psduMap the map of PSDUs to send
110    * \param txParams the TX parameters to use to transmit the PSDUs
111    */
112   void SendPsduMapWithProtection (WifiPsduMap psduMap, WifiTxParameters& txParams);
113 
114   /**
115    * Forward a map of PSDUs down to the PHY layer.
116    *
117    * \param psduMap the map of PSDUs to transmit
118    * \param txVector the TXVECTOR used to transmit the MU PPDU
119    */
120   void ForwardPsduMapDown (WifiConstPsduMap psduMap, WifiTxVector& txVector);
121 
122   /**
123    * Take the necessary actions after that some BlockAck frames are missing
124    * in response to a DL MU PPDU. This method must not be called if all the
125    * expected BlockAck frames were received.
126    *
127    * \param psduMap a pointer to PSDU map transmitted in a DL MU PPDU
128    * \param staMissedBlockAckFrom set of stations we missed a BlockAck frame from
129    * \param nSolicitedStations the number of stations solicited to send a TB PPDU
130    */
131   virtual void BlockAcksInTbPpduTimeout (WifiPsduMap* psduMap,
132                                          const std::set<Mac48Address>* staMissedBlockAckFrom,
133                                          std::size_t nSolicitedStations);
134 
135   /**
136    * Take the necessary actions after that some TB PPDUs are missing in
137    * response to Trigger Frame. This method must not be called if all the
138    * expected TB PPDUs were received.
139    *
140    * \param psduMap a pointer to PSDU map transmitted in a DL MU PPDU
141    * \param staMissedTbPpduFrom set of stations we missed a TB PPDU from
142    * \param nSolicitedStations the number of stations solicited to send a TB PPDU
143    */
144   virtual void TbPpduTimeout (WifiPsduMap* psduMap,
145                               const std::set<Mac48Address>* staMissedTbPpduFrom,
146                               std::size_t nSolicitedStations);
147 
148   /**
149    * Take the necessary actions after that a Block Ack is missing after a
150    * TB PPDU solicited through a Trigger Frame.
151    *
152    * \param psdu the PSDU in the TB PPDU
153    * \param txVector the TXVECTOR used to transmit the TB PPDU
154    */
155   virtual void BlockAckAfterTbPpduTimeout (Ptr<WifiPsdu> psdu, const WifiTxVector& txVector);
156 
157   /**
158    * Return a TXVECTOR for the UL frame that the station will send in response to
159    * the given Trigger frame, configured with the BSS color and transmit power
160    * level to use for the consequent HE TB PPDU.
161    * Note that this method should only be called by non-AP stations only.
162    *
163    * \param trigger the received Trigger frame
164    * \param triggerSender the MAC address of the AP sending the Trigger frame
165    * \return TXVECTOR for the HE TB PPDU frame
166    */
167   WifiTxVector GetHeTbTxVector (CtrlTriggerHeader trigger, Mac48Address triggerSender) const;
168 
169   /**
170    * Build a MU-BAR Trigger Frame starting from the TXVECTOR used to respond to
171    * the MU-BAR (in case of multiple responders, their TXVECTORs need to be
172    * "merged" into a single TXVECTOR) and from the BlockAckReq headers for
173    * every recipient.
174    * Note that the number of recipients must match the number of users addressed
175    * by the given TXVECTOR.
176    *
177    * \param responseTxVector the given TXVECTOR
178    * \param recipients the list of BlockAckReq headers indexed by the station's AID
179    * \return the MPDU containing the built MU-BAR
180    */
181   Ptr<WifiMacQueueItem> PrepareMuBar (const WifiTxVector& responseTxVector,
182                                       std::map<uint16_t, CtrlBAckRequestHeader> recipients) const;
183 
184   /**
185    * Send a Multi-STA Block Ack frame after the reception of some TB PPDUs.
186    *
187    * \param txParams the TX parameters for the Trigger Frame that solicited the TB PPDUs
188    */
189   void SendMultiStaBlockAck (const WifiTxParameters& txParams);
190 
191   /**
192    * Send QoS Null frames in response to a Basic or BSRP Trigger Frame. The number
193    * of QoS Null frames that are actually aggregated depends on the available time
194    * as indicated by the Trigger Frame and is at most 8 (one QoS Null frame per TID).
195    *
196    * \param trigger the Basic or BSRP Trigger Frame content
197    * \param hdr the MAC header of the Basic or BSRP Trigger Frame
198    */
199   void SendQosNullFramesInTbPpdu (const CtrlTriggerHeader& trigger, const WifiMacHeader& hdr);
200 
201   Ptr<ApWifiMac> m_apMac;                             //!< MAC pointer (null if not an AP)
202   Ptr<StaWifiMac> m_staMac;                           //!< MAC pointer (null if not a STA)
203 
204 private:
205   /**
206    * Send the current PSDU map as a DL MU PPDU.
207    */
208   void SendPsduMap (void);
209 
210   /**
211    * Take the necessary actions when receiveing a Basic Trigger Frame.
212    *
213    * \param trigger the Basic Trigger Frame content
214    * \param hdr the MAC header of the Basic Trigger Frame
215    */
216   void ReceiveBasicTrigger (const CtrlTriggerHeader& trigger, const WifiMacHeader& hdr);
217 
218   WifiPsduMap m_psduMap;                              //!< the A-MPDU being transmitted
219   WifiTxParameters m_txParams;                        //!< the TX parameters for the current PPDU
220   Ptr<MultiUserScheduler> m_muScheduler;              //!< Multi-user Scheduler (HE APs only)
221   Ptr<WifiMacQueueItem> m_triggerFrame;               //!< Trigger Frame being sent
222   std::set<Mac48Address> m_staExpectTbPpduFrom;       //!< set of stations expected to send a TB PPDU
223   EventId m_multiStaBaEvent;                          //!< Sending a Multi-STA BlockAck event
224   MuSnrTag m_muSnrTag;                                //!< Tag to attach to Multi-STA BlockAck frames
225   bool m_triggerFrameInAmpdu;                         //!< True if the received A-MPDU contains an MU-BAR
226 };
227 
228 } //namespace ns3
229 
230 #endif /* HE_FRAME_EXCHANGE_MANAGER_H */
231